зеркало из https://github.com/microsoft/PSRule.git
Родитель
98c2513b14
Коммит
791b42d519
194
README.md
194
README.md
|
@ -3,14 +3,18 @@
|
|||
A cross-platform module to validate infrastructure as code (IaC) and objects using PowerShell rules.
|
||||
PSRule works great and integrates with popular continuous integration (CI) systems.
|
||||
|
||||
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/microsoft/PSRule)
|
||||
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)][1]
|
||||
|
||||
Features of PSRule include:
|
||||
|
||||
- [Extensible](docs/features.md#extensible) - Use PowerShell, a flexible scripting language.
|
||||
- [Cross-platform](docs/features.md#cross-platform) - Run on MacOS, Linux, and Windows.
|
||||
- [Reusable](docs/features.md#reusable) - Share rules across teams or organizations.
|
||||
- [Recommendations](docs/features.md#recommendations) - Include detailed instructions to remediate issues.
|
||||
- [DevOps][2] - Built to support DevOps culture and tools.
|
||||
- [Extensible][3] - Define tests using YAML, JSON, or PowerShell format.
|
||||
- [Reusable][4] - Reuse and share rules across teams or organizations.
|
||||
|
||||
[1]: https://open.vscode.dev/microsoft/PSRule
|
||||
[2]: https://microsoft.github.io/PSRule/latest/features/#devops
|
||||
[3]: https://microsoft.github.io/PSRule/latest/features/#extensible
|
||||
[4]: https://microsoft.github.io/PSRule/latest/features/#reusable
|
||||
|
||||
## Project objectives
|
||||
|
||||
|
@ -31,18 +35,23 @@ For continuous integration (CI) systems that do not support PowerShell, run in a
|
|||
- Any reusable validation will have exceptions.
|
||||
Rules must be able to be disabled where they are not applicable.
|
||||
|
||||
Continue reading the [PSRule design specification][spec].
|
||||
Continue reading the [PSRule design specification][5].
|
||||
|
||||
[5]: docs/specs/design-spec.md
|
||||
|
||||
## Support
|
||||
|
||||
This project uses GitHub Issues to track bugs and feature requests.
|
||||
Please search the existing issues before filing new issues to avoid duplicates.
|
||||
|
||||
- For new issues, file your bug or feature request as a new [issue].
|
||||
- For help, discussion, and support questions about using this project, join or start a [discussion].
|
||||
- For new issues, file your bug or feature request as a new [issue][6].
|
||||
- For help, discussion, and support questions about using this project, join or start a [discussion][7].
|
||||
|
||||
Support for this project/ product is limited to the resources listed above.
|
||||
|
||||
[6]: https://github.com/Microsoft/PSRule/issues
|
||||
[7]: https://github.com/microsoft/PSRule/discussions
|
||||
|
||||
## Getting the module
|
||||
|
||||
You can download and install the PSRule module from the PowerShell Gallery.
|
||||
|
@ -65,152 +74,11 @@ Visual Studio Code | Visual Studio Code extension for PSRule. | [latest][extensi
|
|||
|
||||
## Getting started
|
||||
|
||||
The following example shows basic PSRule usage for validating PowerShell objects.
|
||||
For an quickstart example of using PSRule see [Create a standalone rule](https://microsoft.github.io/PSRule/v2/quickstart/standalone-rule/).
|
||||
For specific use cases see [scenarios](#scenarios).
|
||||
|
||||
For frequently asked questions, see the [FAQ](https://microsoft.github.io/PSRule/v2/faq/).
|
||||
|
||||
### Define a rule
|
||||
|
||||
To define a rule, use a `Rule` block saved to a file with the `.Rule.ps1` extension.
|
||||
|
||||
```powershell
|
||||
Rule 'NameOfRule' {
|
||||
# Rule conditions
|
||||
}
|
||||
```
|
||||
|
||||
Within the body of the rule provide one or more conditions.
|
||||
A condition is valid PowerShell that results in `$True` or `$False`.
|
||||
|
||||
For example:
|
||||
|
||||
```powershell
|
||||
Rule 'isFruit' {
|
||||
# Condition to determine if the object is fruit
|
||||
$TargetObject.Name -in 'Apple', 'Orange', 'Pear'
|
||||
}
|
||||
```
|
||||
|
||||
An optional result message can be added to by using the `Recommend` keyword.
|
||||
|
||||
```powershell
|
||||
Rule 'isFruit' {
|
||||
# An recommendation to display in output
|
||||
Recommend 'Fruit is only Apple, Orange and Pear'
|
||||
|
||||
# Condition to determine if the object is fruit
|
||||
$TargetObject.Name -in 'Apple', 'Orange', 'Pear'
|
||||
}
|
||||
```
|
||||
|
||||
The rule is saved to a file named [`isFruit.Rule.ps1`](docs/scenarios/fruit/isFruit.Rule.ps1) file.
|
||||
One or more rules can be defined within a single file.
|
||||
|
||||
### Execute a rule
|
||||
|
||||
To execute the rule use `Invoke-PSRule`.
|
||||
|
||||
For example:
|
||||
|
||||
```powershell
|
||||
# Define objects to validate
|
||||
$items = @();
|
||||
$items += [PSCustomObject]@{ Name = 'Fridge' };
|
||||
$items += [PSCustomObject]@{ Name = 'Apple' };
|
||||
|
||||
# Validate each item using rules saved in current working path
|
||||
$items | Invoke-PSRule;
|
||||
```
|
||||
|
||||
The output of this example is:
|
||||
|
||||
```text
|
||||
TargetName: Fridge
|
||||
|
||||
RuleName Outcome Recommendation
|
||||
-------- ------- --------------
|
||||
isFruit Fail Fruit is only Apple, Orange and Pear
|
||||
|
||||
|
||||
TargetName: Apple
|
||||
|
||||
RuleName Outcome Recommendation
|
||||
-------- ------- --------------
|
||||
isFruit Pass Fruit is only Apple, Orange and Pear
|
||||
```
|
||||
|
||||
### Additional options
|
||||
|
||||
To filter results to only non-fruit results, use `Invoke-PSRule -Outcome Fail`.
|
||||
Passed, failed and error results are shown by default.
|
||||
|
||||
```powershell
|
||||
# Only show non-fruit results
|
||||
$items | Invoke-PSRule -Outcome Fail;
|
||||
```
|
||||
|
||||
For a summary of results for each rule use `Invoke-PSRule -As Summary`.
|
||||
|
||||
For example:
|
||||
|
||||
```powershell
|
||||
# Show rule summary
|
||||
$items | Invoke-PSRule -As Summary;
|
||||
```
|
||||
|
||||
The output of this example is:
|
||||
|
||||
```text
|
||||
RuleName Pass Fail Outcome
|
||||
-------- ---- ---- -------
|
||||
isFruit 1 1 Fail
|
||||
```
|
||||
|
||||
An optional failure reason can be added to the rule block by using the `Reason` keyword.
|
||||
|
||||
```powershell
|
||||
Rule 'isFruit' {
|
||||
# An recommendation to display in output
|
||||
Recommend 'Fruit is only Apple, Orange and Pear'
|
||||
|
||||
# An failure reason to display for non-fruit
|
||||
Reason "$($PSRule.TargetName) is not fruit."
|
||||
|
||||
# Condition to determine if the object is fruit
|
||||
$TargetObject.Name -in 'Apple', 'Orange', 'Pear'
|
||||
}
|
||||
```
|
||||
|
||||
To include the reason with output use `Invoke-PSRule -OutputFormat Wide`.
|
||||
|
||||
For example:
|
||||
|
||||
```powershell
|
||||
# Show failure reason for failing results
|
||||
$items | Invoke-PSRule -OutputFormat Wide;
|
||||
```
|
||||
|
||||
The output of this example is:
|
||||
|
||||
```text
|
||||
|
||||
TargetName: Fridge
|
||||
|
||||
RuleName Outcome Reason Recommendation
|
||||
-------- ------- ------ --------------
|
||||
isFruit Fail Fridge is not fruit. Fruit is only Apple, Orange and Pear
|
||||
|
||||
|
||||
TargetName: Apple
|
||||
|
||||
RuleName Outcome Reason Recommendation
|
||||
-------- ------- ------ --------------
|
||||
isFruit Pass Fruit is only Apple, Orange and Pear
|
||||
```
|
||||
|
||||
The final rule is saved to [`isFruit.Rule.ps1`](docs/scenarios/fruit/isFruit.Rule.ps1).
|
||||
|
||||
### Scenarios
|
||||
|
||||
For walk through examples of PSRule usage see:
|
||||
|
@ -419,19 +287,7 @@ PSRule uses the following schemas:
|
|||
|
||||
## Related projects
|
||||
|
||||
The following projects use or integrate with PSRule.
|
||||
|
||||
Name | Description
|
||||
---- | -----------
|
||||
[PSRule.Rules.Azure] | A suite of rules to validate Azure resources and infrastructure as code (IaC) using PSRule.
|
||||
[PSRule.Rules.Kubernetes] | A suite of rules to validate Kubernetes resources using PSRule.
|
||||
[PSRule.Rules.CAF] | A suite of rules to validate Azure resources against the Cloud Adoption Framework (CAF) using PSRule.
|
||||
[PSRule.Rules.GitHub] | A suite of rules to validate GitHub repositories using PSRule.
|
||||
[PSRule.Rules.MSFT.OSS] | A suite of rules to validate repositories against Microsoft Open Source Software (OSS) requirements.
|
||||
[PSRule.Monitor] | Send and query PSRule analysis results in Azure Monitor.
|
||||
[PSRule-pipelines] | Validate infrastructure as code (IaC) and DevOps repositories using Azure Pipelines.
|
||||
[ps-rule] | Validate infrastructure as code (IaC) and DevOps repositories using GitHub Actions.
|
||||
[PSRule-vscode] | Visual Studio Code extension for PSRule.
|
||||
For a list of projects and integrations see [Related projects](https://microsoft.github.io/PSRule/v2/related-projects/).
|
||||
|
||||
## Changes and versioning
|
||||
|
||||
|
@ -462,20 +318,8 @@ or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any addi
|
|||
|
||||
This project is [licensed under the MIT License](LICENSE).
|
||||
|
||||
[issue]: https://github.com/Microsoft/PSRule/issues
|
||||
[discussion]: https://github.com/microsoft/PSRule/discussions
|
||||
[install]: https://microsoft.github.io/PSRule/v2/install-instructions/
|
||||
[module-psrule]: https://www.powershellgallery.com/packages/PSRule
|
||||
[extension-vscode]: https://marketplace.visualstudio.com/items?itemName=bewhite.psrule-vscode
|
||||
[extension-pipelines]: https://marketplace.visualstudio.com/items?itemName=bewhite.ps-rule
|
||||
[extension-actions]: https://github.com/marketplace/actions/psrule
|
||||
[PSRule.Rules.Azure]: https://github.com/microsoft/PSRule.Rules.Azure
|
||||
[PSRule.Rules.Kubernetes]: https://github.com/microsoft/PSRule.Rules.Kubernetes
|
||||
[PSRule.Rules.CAF]: https://github.com/microsoft/PSRule.Rules.CAF
|
||||
[PSRule.Rules.GitHub]: https://github.com/microsoft/PSRule.Rules.GitHub
|
||||
[PSRule.Rules.MSFT.OSS]: https://github.com/microsoft/PSRule.Rules.MSFT.OSS
|
||||
[PSRule.Monitor]: https://github.com/microsoft/PSRule.Monitor
|
||||
[PSRule-pipelines]: https://github.com/microsoft/PSRule-pipelines
|
||||
[ps-rule]: https://github.com/microsoft/ps-rule
|
||||
[PSRule-vscode]: https://github.com/microsoft/PSRule-vscode
|
||||
[spec]: docs/specs/design-spec.md
|
||||
|
|
|
@ -12,7 +12,30 @@
|
|||
color:#e91e63;
|
||||
}
|
||||
|
||||
.experimental {
|
||||
color:rgb(124, 77, 255);
|
||||
}
|
||||
|
||||
:root {
|
||||
--md-success-invert-color: #fff;
|
||||
--md-success-color: #107c10;
|
||||
}
|
||||
|
||||
:root {
|
||||
--md-admonition-icon--experimental: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M8 8.807V3.5h-.563a.75.75 0 0 1 0-1.5h9.125a.75.75 0 0 1 0 1.5H16v5.307l5.125 9.301c.964 1.75-.302 3.892-2.299 3.892H5.174c-1.998 0-3.263-2.142-2.3-3.892L8 8.807zM14.5 3.5h-5V9a.75.75 0 0 1-.093.362L7.127 13.5h9.746l-2.28-4.138A.75.75 0 0 1 14.5 9V3.5zM4.189 18.832 6.3 15h11.4l2.111 3.832a1.125 1.125 0 0 1-.985 1.668H5.174a1.125 1.125 0 0 1-.985-1.668z"/></svg>')
|
||||
}
|
||||
.md-typeset .admonition.experimental,
|
||||
.md-typeset details.experimental {
|
||||
border-color: rgb(124, 77, 255)
|
||||
}
|
||||
.md-typeset .experimental > .admonition-title,
|
||||
.md-typeset .experimental > summary {
|
||||
background-color: rgba(124,77,255,.1);;
|
||||
border-color: rgb(124, 77, 255);
|
||||
}
|
||||
.md-typeset .experimental > .admonition-title::before,
|
||||
.md-typeset .experimental > summary::before {
|
||||
background-color: rgb(124, 77, 255);
|
||||
-webkit-mask-image: var(--md-admonition-icon--experimental);
|
||||
mask-image: var(--md-admonition-icon--experimental);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Writing rules
|
||||
# Testing infrastructure
|
||||
|
||||
You can use PSRule to create tests for Infrastructure as Code (IaC).
|
||||
Each test is called a _rule_.
|
||||
|
@ -70,7 +70,7 @@ In this section the same rule will be authored using YAML, JSON, and PowerShell.
|
|||
1. 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.
|
||||
2. Name your rule with a unique name.
|
||||
3. The `condition` block determines the checks PSRule will use to test `settings.json`.
|
||||
3. The `condition` property determines the checks PSRule will use to test `settings.json`.
|
||||
Specifically, the object path `configures.supportsHttpsTrafficOnly` must exist and be set to `true`.
|
||||
|
||||
=== "JSON"
|
||||
|
@ -99,7 +99,7 @@ In this section the same rule will be authored using YAML, JSON, and PowerShell.
|
|||
1. 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.
|
||||
2. Name your rule with a unique name.
|
||||
3. The `condition` block determines the checks PSRule will use to test `settings.json`.
|
||||
3. The `condition` propert determines the checks PSRule will use to test `settings.json`.
|
||||
Specifically, the object path `configures.supportsHttpsTrafficOnly` must exist and be set to `true`.
|
||||
|
||||
=== "PowerShell"
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Using expressions
|
||||
|
||||
PSRule allows you to write rules using YAML, JSON, or PowerShell.
|
||||
This offers a lot of flexibility to use PSRule for a variety of use cases.
|
||||
Some examples of use cases for each format include:
|
||||
|
||||
- **YAML** — Start authoring quickly with minimal knowledge of PowerShell.
|
||||
- **JSON** — Generate rules automatically using automation tools.
|
||||
- **PowerShell** — Integrate with other tools using PowerShell cmdlets.
|
||||
|
||||
!!! Abstract
|
||||
This topic covers the differences and limitations between authoring rules using YAML, JSON, and PowerShell.
|
||||
For an example of authoring rules see [Writing rules][1] or [Testing infrastructure][2] topics.
|
||||
|
||||
[1]: ../quickstart/standalone-rule.md
|
||||
[2]: testing-infrastructure.md
|
||||
|
||||
## Language comparison
|
||||
|
||||
Expressions and assertion methods can be used to build similar conditions.
|
||||
|
||||
- **Expressions** — Schema-based conditions written in YAML or JSON.
|
||||
Expressions can be used in rules and selectors.
|
||||
- **Assertion methods** — PowerShell-based condition helpers that make rules faster to author.
|
||||
Assertion methods can be used in combination with standard PowerShell code to build rules or conventions.
|
||||
|
||||
### Quick reference
|
||||
|
||||
In most cases expressions and assertion method names match.
|
||||
There are some cases where these names do not directly align.
|
||||
This lookup table provides a quick reference for expressions and their assertion method counterpart.
|
||||
|
||||
Expression | Assertion method
|
||||
---------- | ----------------
|
||||
Contains | Contains
|
||||
Count | Count
|
||||
Equals [^1] | _n/a_
|
||||
EndsWith | EndsWith
|
||||
Exists | HasField
|
||||
Greater | Greater
|
||||
GreaterOrEquals | GreaterOrEqual
|
||||
HasDefault | HasDefaultValue
|
||||
HasSchema | HasJsonSchema
|
||||
HasValue [^1] | _n/a_
|
||||
In | In
|
||||
IsLower | IsLower
|
||||
IsString | IsString
|
||||
IsUpper | IsUpper
|
||||
Less | Less
|
||||
LessOrEquals | LessOrEqual
|
||||
Match | Match
|
||||
NotEquals | _n/a_
|
||||
NotIn | NotIn
|
||||
NotMatch | NotMatch
|
||||
SetOf | SetOf
|
||||
StartsWith | StartsWith
|
||||
Subset | Subset
|
||||
Version | Version
|
||||
_n/a_ | FileHeader
|
||||
_n/a_ | FilePath
|
||||
_n/a_ | HasFields
|
||||
_n/a_ | HasFieldValue [^1]
|
||||
IsArray | IsArray
|
||||
IsBoolean | IsBoolean
|
||||
IsDateTime | IsDateTime
|
||||
IsInteger | IsInteger
|
||||
IsNumeric | IsNumeric
|
||||
_n/a_ | JsonSchema
|
||||
Exists | NotHasField
|
||||
_n/a_ | NotNull
|
||||
NotWithinPath | NotWithinPath
|
||||
_n/a_ | Null
|
||||
_n/a_ | NullOrEmpty
|
||||
_n/a_ | TypeOf
|
||||
WithinPath | WithinPath
|
||||
|
||||
[^1]: The `Equals`, `HasValue` and expression and `HasFieldValue` are similar.
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
tags:
|
||||
- language
|
||||
---
|
||||
|
||||
# PSRule_Assert
|
||||
|
||||
## about_PSRule_Assert
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
---
|
||||
tags:
|
||||
- language
|
||||
---
|
||||
|
||||
# PSRule_Expressions
|
||||
|
||||
## about_PSRule_Expressions
|
||||
|
|
|
@ -28,7 +28,7 @@ def replace_maml(markdown: str, page: mkdocs.structure.nav.Page, config: mkdocs.
|
|||
markdown = markdown.replace("## about_PSRule_Selectors", "")
|
||||
markdown = markdown.replace("## about_PSRule_SuppressionGroups", "")
|
||||
markdown = markdown.replace("## about_PSRule_Variables", "")
|
||||
markdown = markdown.replace("# PSRule_Assert", "# Assertion helpers")
|
||||
markdown = markdown.replace("# PSRule_Assert", "# Assertion methods")
|
||||
markdown = markdown.replace("# PSRule_Baseline", "# Baselines")
|
||||
markdown = markdown.replace("# PSRule_Badges", "# Badges")
|
||||
markdown = markdown.replace("# PSRule_Conventions", "# Conventions")
|
||||
|
|
|
@ -20,7 +20,7 @@ Install and use PSRule with GitHub Actions by referencing the `Microsoft/ps-rule
|
|||
|
||||
```yaml
|
||||
- name: Analyze Azure template files
|
||||
uses: Microsoft/ps-rule@v1.10.0
|
||||
uses: Microsoft/ps-rule@v1.12.0
|
||||
```
|
||||
|
||||
This will automatically install compatible versions of all dependencies.
|
||||
|
@ -83,6 +83,8 @@ Use the following command line examples from a PowerShell terminal to install or
|
|||
```
|
||||
|
||||
=== "For all users"
|
||||
Open PowerShell with _Run as administrator_ on Windows or `sudo pwsh` on Linux.
|
||||
|
||||
To install PSRule for all users (requires admin/ root permissions) use:
|
||||
|
||||
```powershell
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
{
|
||||
// Synopsis: Image files are not permitted.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Rule",
|
||||
"metadata": {
|
||||
"name": "Json.FileType"
|
||||
},
|
||||
"spec": {
|
||||
"type": [
|
||||
"System.IO.FileInfo"
|
||||
],
|
||||
"condition": {
|
||||
"field": "Extension",
|
||||
"notIn": [
|
||||
".jpg",
|
||||
".png"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,7 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
# Synopsis: Image files are not permitted.
|
||||
Rule 'PS.FileType' -Type 'System.IO.FileInfo' {
|
||||
$Assert.NotIn($TargetObject, 'Extension', @('.jpg', '.png'))
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
---
|
||||
# Synopsis: Image files are not permitted.
|
||||
apiVersion: github.com/microsoft/PSRule/v1
|
||||
kind: Rule
|
||||
metadata:
|
||||
name: Yaml.FileType
|
||||
spec:
|
||||
type:
|
||||
- System.IO.FileInfo
|
||||
condition:
|
||||
field: Extension
|
||||
notIn:
|
||||
- .jpg
|
||||
- .png
|
|
@ -0,0 +1,35 @@
|
|||
[
|
||||
{
|
||||
// Synopsis: Find services with an automatic start type.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Selector",
|
||||
"metadata": {
|
||||
"name": "Json.IsAutomaticService"
|
||||
},
|
||||
"spec": {
|
||||
"if": {
|
||||
"field": "StartType",
|
||||
"startsWith": "Automatic",
|
||||
"convert": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// Synopsis: Automatic services should be running.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Rule",
|
||||
"metadata": {
|
||||
"name": "Json.ServiceStarted"
|
||||
},
|
||||
"spec": {
|
||||
"with": [
|
||||
"Json.IsAutomaticService"
|
||||
],
|
||||
"condition": {
|
||||
"field": "Status",
|
||||
"equals": "Running",
|
||||
"convert": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
# Synopsis: Automatic services should be running.
|
||||
Rule 'PS.ServiceStarted' -With 'IsAutomaticService' {
|
||||
$status = $TargetObject.Status.ToString()
|
||||
$Assert.HasFieldValue($status, '.', 'Running')
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
---
|
||||
# Synopsis: Find services with an automatic start type.
|
||||
apiVersion: github.com/microsoft/PSRule/v1
|
||||
kind: Selector
|
||||
metadata:
|
||||
name: IsAutomaticService
|
||||
spec:
|
||||
if:
|
||||
field: StartType
|
||||
startsWith: Automatic
|
||||
convert: true
|
||||
|
||||
---
|
||||
# Synopsis: Automatic services should be running.
|
||||
apiVersion: github.com/microsoft/PSRule/v1
|
||||
kind: Rule
|
||||
metadata:
|
||||
name: Yaml.ServiceStarted
|
||||
spec:
|
||||
with:
|
||||
- IsAutomaticService
|
||||
condition:
|
||||
field: Status
|
||||
equals: Running
|
||||
convert: true
|
|
@ -0,0 +1,460 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Create a standalone rule
|
||||
|
||||
You can use PSRule to create tests for PowerShell objects piped to PSRule for validation.
|
||||
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.
|
||||
In this quickstart, will be using native PowerShell objects.
|
||||
For an example of reading objects from disk, continue reading [Testing infrastructure][1].
|
||||
|
||||
[1]: ../authoring/testing-infrastructure.md
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For this quickstart, PSRule must be installed locally on MacOS, Linux, or Windows.
|
||||
To install PSRule locally, open PowerShell and run the following `Install-Module` command.
|
||||
If you don't have PowerShell installed, complete [Installing PowerShell][2] first.
|
||||
|
||||
```powershell title="PowerShell"
|
||||
Install-Module -Name 'PSRule' -Repository PSGallery -Scope CurrentUser
|
||||
```
|
||||
|
||||
!!! Tip
|
||||
PowerShell is installed by default on Windows.
|
||||
If these instructions don't work for you,
|
||||
your administrator may have restricted how PowerShell can be used in your environment.
|
||||
You or your administrator may be able to install PSRule for all users as a local administrator.
|
||||
See [Getting the modules][3] for instructions on how to do this.
|
||||
|
||||
!!! Tip
|
||||
To make you editing experience even better, consider installing the Visual Studio Code extension.
|
||||
|
||||
[2]: ../install-instructions.md#installing-powershell
|
||||
[3]: ../install-instructions.md#getting-the-modules
|
||||
|
||||
## Scenario - Test for image files
|
||||
|
||||
In our quickstart scenario, we have been tasked with creating a rule to test for image files.
|
||||
When a file ending with the `.jpg` or `.png` extension is found the rule should fail.
|
||||
|
||||
We will be using the following PowerShell code to get a list of files.
|
||||
|
||||
```powershell title="PowerShell"
|
||||
$pathToSearch = $Env:HOME;
|
||||
$files = Get-ChildItem -Path $pathToSearch -File -Recurse;
|
||||
```
|
||||
|
||||
!!! Info
|
||||
The path to search `$Env:HOME` defaults to the current user's home directory.
|
||||
This directory is used so this quickstart works on Windows and Linux operating systems.
|
||||
Feel free to update this path to a more suitable directory on your local machine.
|
||||
|
||||
### Define the file type rule
|
||||
|
||||
Before an object can be tested with PSRule, one or more rules must be defined.
|
||||
Each rule is defined in a file named with the suffix `.Rule.yaml`, `.Rule.jsonc`, or `.Rule.ps1`.
|
||||
Multiple rules can be defined in a single file.
|
||||
|
||||
A rule that fail on files with `.jpg` or `.png` extensions is shown in YAML, JSON, and PowerShell formats.
|
||||
You only need to choose one format, however you can choose to create all three to try out each format.
|
||||
|
||||
=== "YAML"
|
||||
|
||||
Create the `FileType.Rule.yaml` file with the following contents.
|
||||
This file can be created in Visual Studio Code or any text editor.
|
||||
Make a note of the location you save `FileType.Rule.yaml`.
|
||||
|
||||
```yaml title="YAML"
|
||||
---
|
||||
# Synopsis: Image files are not permitted.
|
||||
apiVersion: github.com/microsoft/PSRule/v1
|
||||
kind: Rule
|
||||
metadata:
|
||||
name: Yaml.FileType
|
||||
spec:
|
||||
type:
|
||||
- System.IO.FileInfo
|
||||
condition:
|
||||
field: Extension
|
||||
notIn:
|
||||
- .jpg
|
||||
- .png
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your rule in a line comment above your rule.
|
||||
This will be shown in output as the default recommendation.
|
||||
For this to be interpreted by PSRule, only a single line is allowed.
|
||||
2. Name your rule with a unique name `Yaml.FileType`.
|
||||
3. The `type` property ensures the rule will only run for file info objects.
|
||||
Other objects that might be piped to PSRule will be skipped by the `Yaml.FileType` rule.
|
||||
4. The `condition` property determines the checks PSRule will use to test each file returned with `Get-ChildItem`.
|
||||
Specifically, the `Extension` property of each `FileInfo` object will be compared.
|
||||
The value of `Extension` should not be either `.jpg` or `.png`.
|
||||
|
||||
=== "JSON"
|
||||
|
||||
Create the `FileType.Rule.jsonc` file with the following contents.
|
||||
This file can be created in Visual Studio Code or any text editor.
|
||||
Make a note of the location you save `FileType.Rule.jsonc`.
|
||||
|
||||
```json title="JSON"
|
||||
[
|
||||
{
|
||||
// Synopsis: Image files are not permitted.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Rule",
|
||||
"metadata": {
|
||||
"name": "Json.FileType"
|
||||
},
|
||||
"spec": {
|
||||
"type": [
|
||||
"System.IO.FileInfo"
|
||||
],
|
||||
"condition": {
|
||||
"field": "Extension",
|
||||
"notIn": [
|
||||
".jpg",
|
||||
".png"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your rule in a line comment above your rule.
|
||||
This will be shown in output as the default recommendation.
|
||||
For this to be interpreted by PSRule, only a single line is allowed.
|
||||
2. Name your rule with a unique name `Json.FileType`.
|
||||
3. The `type` property ensures the rule will only run for file info objects.
|
||||
Other objects that might be piped to PSRule will be skipped by the `Json.FileType` rule.
|
||||
4. The `condition` property determines the checks PSRule will use to test each file returned with `Get-ChildItem`.
|
||||
Specifically, the `Extension` property of each `FileInfo` object will be compared.
|
||||
The value of `Extension` should not be either `.jpg` or `.png`.
|
||||
|
||||
=== "PowerShell"
|
||||
|
||||
Create the `FileType.Rule.ps1` file with the following contents.
|
||||
This file can be created in Visual Studio Code, Windows PowerShell ISE, or any text editor.
|
||||
Make a note of the location you save `FileType.Rule.ps1`.
|
||||
|
||||
```powershell title="PowerShell"
|
||||
# Synopsis: Image files are not permitted.
|
||||
Rule 'PS.FileType' -Type 'System.IO.FileInfo' {
|
||||
$Assert.NotIn($TargetObject, 'Extension', @('.jpg', '.png'))
|
||||
}
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your rule in a line comment above your rule.
|
||||
This will be shown in output as the default recommendation.
|
||||
For this to be interpreted by PSRule, only a single line is allowed.
|
||||
2. Name your rule with a unique name `PS.FileType`.
|
||||
3. The `-Type` parameter ensures the rule will only run for file info objects.
|
||||
Other objects that might be piped to PSRule will be skipped by the `PS.FileType` rule.
|
||||
4. The condition contained within the curly braces `{ }` determines the checks PSRule will use to test each file returned with `Get-ChildItem`.
|
||||
5. The `$Assert.NotIn` method checks the `Extension` property is not set to `.jpg` or `.png`.
|
||||
|
||||
### Testing file extensions
|
||||
|
||||
You can test the rule by using the `Invoke-PSRule` command.
|
||||
For example:
|
||||
|
||||
```powershell title="PowerShell"
|
||||
$pathToSearch = $Env:HOME;
|
||||
$files = Get-ChildItem -Path $pathToSearch -File -Recurse;
|
||||
|
||||
# The path to the rule file. Update this to the location of your saved file.
|
||||
$rulePath = 'C:\temp\FileType.Rule.ps1'
|
||||
# Or the directory can be used to find all rules in the path:
|
||||
# $rulePath = 'C:\temp\'
|
||||
|
||||
# Test the rule
|
||||
$files | Invoke-PSRule -Path $rulePath
|
||||
```
|
||||
|
||||
After running `Invoke-PSRule` you will get output which includes all files in the _pathToSeach_.
|
||||
Files with a `.jpg` or `.png` extension should have the outcome of `Fail`.
|
||||
All other files should report an outcome of `Pass`.
|
||||
|
||||
For example:
|
||||
|
||||
```text title="Output"
|
||||
TargetName: main.html
|
||||
|
||||
RuleName Outcome Recommendation
|
||||
-------- ------- --------------
|
||||
Yaml.FileType Pass Image files are not permitted.
|
||||
|
||||
TargetName: favicon.png
|
||||
|
||||
RuleName Outcome Recommendation
|
||||
-------- ------- --------------
|
||||
Yaml.FileType Fail Image files are not permitted.
|
||||
```
|
||||
|
||||
!!! Tip
|
||||
- If you didn't get any results with `Fail` try creating or saving a `.jpg` file in _pathToSeach_.
|
||||
- If you have too many `Pass` results you can filter the output to only fails by using `-Outcome Fail`.
|
||||
For example:
|
||||
|
||||
```powershell
|
||||
$files | Invoke-PSRule -Path $rulePath -Outcome Fail
|
||||
```
|
||||
|
||||
## Scenario - Test for service status
|
||||
|
||||
[:octicons-beaker-24:{ .experimental } Pre-release][v2]{ .experimental } · :octicons-milestone-24: v2.0.0
|
||||
|
||||
In our quickstart scenario, we have been tasked to:
|
||||
|
||||
- Find any services that are set to start automatically with `StartType` begining with `Automatic`.
|
||||
- Fail for any service with a `Status` other than `Running`.
|
||||
|
||||
We will be using the following PowerShell code to get a list of local services.
|
||||
|
||||
```powershell title="PowerShell"
|
||||
$services = Get-Service
|
||||
```
|
||||
|
||||
!!! Note
|
||||
This scenario is designed for Windows clients.
|
||||
The PowerShell cmdlet `Get-Service` is only available on Windows.
|
||||
|
||||
[v2]: ../CHANGELOG-v2.md
|
||||
|
||||
### Define a selector
|
||||
|
||||
A _selector_ can be used to filter a list of all services to only services that are set to start automatically.
|
||||
Selectors use YAML or JSON expressions are are similar to rules in many ways.
|
||||
A selector determines _if_ the rule will be run or skipped.
|
||||
|
||||
- If the selector is `true` then the rule will be run and either pass or fail.
|
||||
- If the selector is `false` then the rule will be skipped.
|
||||
|
||||
=== "YAML"
|
||||
|
||||
Create the `Service.Rule.yaml` file with the following contents.
|
||||
This file can be created in Visual Studio Code or any text editor.
|
||||
Make a note of the location you save `Service.Rule.yaml`.
|
||||
|
||||
```yaml title="YAML"
|
||||
---
|
||||
# Synopsis: Find services with an automatic start type.
|
||||
apiVersion: github.com/microsoft/PSRule/v1
|
||||
kind: Selector
|
||||
metadata:
|
||||
name: Yaml.IsAutomaticService
|
||||
spec:
|
||||
if:
|
||||
field: StartType
|
||||
startsWith: Automatic
|
||||
convert: true
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your selector in a line comment above your rule.
|
||||
2. Name your selector with a unique name `Yaml.IsAutomaticService`.
|
||||
3. The `if` property determines if PSRule will evaluate the service rule.
|
||||
Specifically, the `StartType` property of each service object will be compared.
|
||||
The value of `StartType` must start with `Automatic`.
|
||||
4. The `convert` property automatically converts the enum type of `StartType` to a string.
|
||||
|
||||
=== "JSON"
|
||||
|
||||
Create the `Service.Rule.jsonc` file with the following contents.
|
||||
This file can be created in Visual Studio Code or any text editor.
|
||||
Make a note of the location you save `Service.Rule.jsonc`.
|
||||
|
||||
```json title="JSON"
|
||||
[
|
||||
{
|
||||
// Synopsis: Find services with an automatic start type.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Selector",
|
||||
"metadata": {
|
||||
"name": "Json.IsAutomaticService"
|
||||
},
|
||||
"spec": {
|
||||
"if": {
|
||||
"field": "StartType",
|
||||
"startsWith": "Automatic",
|
||||
"convert": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your selector in a line comment above your rule.
|
||||
2. Name your selector with a unique name `Json.IsAutomaticService`.
|
||||
3. The `if` property determines if PSRule will evaluate the service rule.
|
||||
Specifically, the `StartType` property of each service object will be compared.
|
||||
The value of `StartType` must start with `Automatic`.
|
||||
4. The `convert` property automatically converts the enum type of `StartType` to a string.
|
||||
|
||||
### Define the service rule
|
||||
|
||||
Similar to the selector, the `Status` field will be tested to determine if the service is `Running`.
|
||||
|
||||
=== "YAML"
|
||||
|
||||
Append the following contents to the existing `Service.Rule.yaml` file.
|
||||
|
||||
```yaml title="YAML"
|
||||
---
|
||||
# Synopsis: Automatic services should be running.
|
||||
apiVersion: github.com/microsoft/PSRule/v1
|
||||
kind: Rule
|
||||
metadata:
|
||||
name: Yaml.ServiceStarted
|
||||
spec:
|
||||
with:
|
||||
- Yaml.IsAutomaticService
|
||||
condition:
|
||||
field: Status
|
||||
equals: Running
|
||||
convert: true
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your rule in a line comment above your rule.
|
||||
This will be shown in output as the default recommendation.
|
||||
For this to be interpreted by PSRule, only a single line is allowed.
|
||||
2. Name your rule with a unique name `Yaml.ServiceStarted`.
|
||||
3. The `with` property indicates to only run this rule on selected service objects.
|
||||
The `Yaml.IsAutomaticService` selector must first return `true` otherwise this rule will be skipped.
|
||||
4. The `condition` property determines the checks PSRule will use to test each service.
|
||||
Specifically, the `Status` property will be compared.
|
||||
The value of `Status` must be `Running`.
|
||||
5. The `convert` property automatically converts the enum type of `Status` to a string.
|
||||
|
||||
=== "JSON"
|
||||
|
||||
Update the contents of `Service.Rule.jsonc` to the following.
|
||||
|
||||
```json title="JSON"
|
||||
[
|
||||
{
|
||||
// Synopsis: Find services with an automatic start type.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Selector",
|
||||
"metadata": {
|
||||
"name": "Json.IsAutomaticService"
|
||||
},
|
||||
"spec": {
|
||||
"if": {
|
||||
"field": "StartType",
|
||||
"startsWith": "Automatic",
|
||||
"convert": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// Synopsis: Automatic services should be running.
|
||||
"apiVersion": "github.com/microsoft/PSRule/v1",
|
||||
"kind": "Rule",
|
||||
"metadata": {
|
||||
"name": "Json.ServiceStarted"
|
||||
},
|
||||
"spec": {
|
||||
"with": [
|
||||
"Json.IsAutomaticService"
|
||||
],
|
||||
"condition": {
|
||||
"field": "Status",
|
||||
"equals": "Running",
|
||||
"convert": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your rule in a line comment above your rule.
|
||||
This will be shown in output as the default recommendation.
|
||||
For this to be interpreted by PSRule, only a single line is allowed.
|
||||
2. Name your rule with a unique name `Json.ServiceStarted`.
|
||||
3. The `with` property indicates to only run this rule on selected service objects.
|
||||
The `Json.IsAutomaticService` selector must first return `true` otherwise this rule will be skipped.
|
||||
4. The `condition` property determines the checks PSRule will use to test each service.
|
||||
Specifically, the `Status` property will be compared.
|
||||
The value of `Status` must be `Running`.
|
||||
5. The `convert` property automatically converts the enum type of `Status` to a string.
|
||||
|
||||
=== "PowerShell"
|
||||
|
||||
Create the `Service.Rule.ps1` file with the following contents.
|
||||
This file can be created in Visual Studio Code, Windows PowerShell ISE, or any text editor.
|
||||
Make a note of the location you save `Service.Rule.ps1`.
|
||||
|
||||
```powershell title="PowerShell"
|
||||
# Synopsis: Automatic services should be running.
|
||||
Rule 'PS.ServiceStarted' -With 'Yaml.IsAutomaticService' {
|
||||
$status = $TargetObject.Status.ToString()
|
||||
$Assert.HasFieldValue($status, '.', 'Running')
|
||||
}
|
||||
```
|
||||
|
||||
1. Use a short `Synopsis: ` to describe your rule in a line comment above your rule.
|
||||
This will be shown in output as the default recommendation.
|
||||
For this to be interpreted by PSRule, only a single line is allowed.
|
||||
2. Name your rule with a unique name `PS.ServiceStarted`.
|
||||
3. The `-With` parameter indicates to only run this rule on selected service objects.
|
||||
The `Yaml.IsAutomaticService` selector must first return `true` otherwise this rule will be skipped.
|
||||
4. The condition contained within the curly braces `{ }` determines the checks PSRule will use to test each service object.
|
||||
5. The `Status` enum property is converted to a string.
|
||||
6. The `$Assert.HasFieldValue` method checks the converted `Status` property is set to `Running`.
|
||||
|
||||
### Testing service objects
|
||||
|
||||
You can test the rule with service object by using the `Invoke-PSRule` command.
|
||||
For example:
|
||||
|
||||
```powershell title="PowerShell"
|
||||
$services = Get-Service
|
||||
|
||||
# The directoy path to the rule file. Update this to the location of your saved file.
|
||||
$rulePath = 'C:\temp\'
|
||||
|
||||
# Test the rule
|
||||
$services | Invoke-PSRule -Path $rulePath
|
||||
```
|
||||
|
||||
After running `Invoke-PSRule` you will get output which include for services that start automatically.
|
||||
Services that are `Running` should pass whereas other stopped services should fail.
|
||||
For manual or disabled services a warning will be generated indicating that no matching rules were found.
|
||||
|
||||
For example:
|
||||
|
||||
```text title="Output"
|
||||
TargetName: edgeupdate
|
||||
|
||||
RuleName Outcome Recommendation
|
||||
-------- ------- --------------
|
||||
PS.ServiceStarted Fail Automatic services should be running.
|
||||
Yaml.ServiceStarted Fail Automatic services should be running.
|
||||
Json.ServiceStarted Fail Automatic services should be running.
|
||||
|
||||
|
||||
TargetName: EventLog
|
||||
|
||||
RuleName Outcome Recommendation
|
||||
-------- ------- --------------
|
||||
PS.ServiceStarted Pass Automatic services should be running.
|
||||
Yaml.ServiceStarted Pass Automatic services should be running.
|
||||
Json.ServiceStarted Pass Automatic services should be running.
|
||||
|
||||
WARNING: Target object 'TermService' has not been processed because no matching rules were found.
|
||||
```
|
||||
|
||||
!!! Tip
|
||||
You can disable the warning by setting [Execution.NotProcessedWarning][5] option.
|
||||
Alternatively you can ignore the warning by using the `-WarningAction SilentlyContinue` parameter.
|
||||
|
||||
[5]: ../concepts/PSRule/en-US/about_PSRule_Options.md#executionnotprocessedwarning
|
|
@ -9,8 +9,11 @@ For example, Azure resources can be validated to match an internal standard or b
|
|||
|
||||
Consider using or contributing these pre-built rule modules instead:
|
||||
|
||||
- [PSRule.Rules.Azure]
|
||||
- [PSRule.Rules.CAF]
|
||||
- [PSRule.Rules.Azure][1]
|
||||
- [PSRule.Rules.CAF][2]
|
||||
|
||||
[1]: https://github.com/Azure/PSRule.Rules.Azure
|
||||
[2]: https://github.com/microsoft/PSRule.Rules.CAF
|
||||
|
||||
This scenario covers the following:
|
||||
|
||||
|
@ -238,5 +241,3 @@ Rule 'storageAccounts.UseHttps' -If { ResourceType 'Microsoft.Storage/storageAcc
|
|||
- [common.Rule.ps1](common.Rule.ps1) - ResourceType helper function.
|
||||
|
||||
[azure-docs-secure-transfer]: https://docs.microsoft.com/azure/storage/common/storage-require-secure-transfer
|
||||
[PSRule.Rules.Azure]: https://github.com/Microsoft/PSRule.Rules.Azure
|
||||
[PSRule.Rules.CAF]: https://github.com/Microsoft/PSRule.Rules.CAF
|
||||
|
|
|
@ -4,7 +4,6 @@ author: BernieWhite
|
|||
|
||||
# Validating locally
|
||||
|
||||
While preparing infrastructure code artifacts, Azure resources can be validated locally.
|
||||
PSRule can be installed locally on MacOS, Linux, and Windows for local validation.
|
||||
|
||||
!!! Tip
|
||||
|
@ -16,7 +15,7 @@ PSRule can be installed locally on MacOS, Linux, and Windows for local validatio
|
|||
|
||||
[:octicons-download-24: Extension][2]
|
||||
|
||||
An extension for Visual Studio Code is available for an integrated experience using PSRule for Azure.
|
||||
An extension for Visual Studio Code is available for an integrated experience using PSRule.
|
||||
The Visual Studio Code extension includes a built-in `PSRule: Run analysis` task.
|
||||
|
||||
<p align="center">
|
||||
|
|
10
mkdocs.yml
10
mkdocs.yml
|
@ -38,8 +38,11 @@ nav:
|
|||
- Features: features.md
|
||||
- FAQ: faq.md
|
||||
- Installation: install-instructions.md
|
||||
- Quickstarts:
|
||||
- Create a standalone rule: quickstart/standalone-rule.md
|
||||
- Authoring rules:
|
||||
- Writing rules: authoring/writing-rules.md
|
||||
- Testing infrastructure: authoring/testing-infrastructure.md
|
||||
- Using expressions: authoring/using-expressions.md
|
||||
- Storing and naming rules: authoring/storing-rules.md
|
||||
- Packaging rules in a module: authoring/packaging-rules.md
|
||||
- Writing rule help: authoring/writing-rule-help.md
|
||||
|
@ -80,7 +83,7 @@ nav:
|
|||
- New-PSRuleOption: commands/PSRule/en-US/New-PSRuleOption.md
|
||||
- Set-PSRuleOption: commands/PSRule/en-US/Set-PSRuleOption.md
|
||||
- Test-PSRuleTarget: commands/PSRule/en-US/Test-PSRuleTarget.md
|
||||
- Assertion helpers: concepts/PSRule/en-US/about_PSRule_Assert.md
|
||||
- Assertion methods: concepts/PSRule/en-US/about_PSRule_Assert.md
|
||||
- Baselines: concepts/PSRule/en-US/about_PSRule_Baseline.md
|
||||
- Badges: concepts/PSRule/en-US/about_PSRule_Badges.md
|
||||
- Conventions: concepts/PSRule/en-US/about_PSRule_Conventions.md
|
||||
|
@ -128,6 +131,9 @@ plugins:
|
|||
# on_nav: "docs.hooks:build_reference_nav"
|
||||
- search
|
||||
- git-revision-date
|
||||
- redirects:
|
||||
redirect_maps:
|
||||
'authoring/writing-rules.md': 'authoring/testing-infrastructure.md'
|
||||
|
||||
extra:
|
||||
version:
|
||||
|
|
|
@ -322,7 +322,7 @@
|
|||
<div>
|
||||
{% include ".icons/octicons/workflow-24.svg" %}
|
||||
<h3 class="h4 text-brand font-weight-600 mb-3">Extensible</h3>
|
||||
<p>Define rules using YAML, JSON, or PowerShell format.</p>
|
||||
<p>Define tests using YAML, JSON, or PowerShell format.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a class="tile" href="{{ 'features/' | url }}#reusable" target="_self" rel="noopener">
|
||||
|
|
Загрузка…
Ссылка в новой задаче