Родитель
6c63026449
Коммит
58cf1e5bf7
|
@ -141,18 +141,22 @@ stages:
|
|||
displayName: 'PowerShell coverage'
|
||||
coverage: 'true'
|
||||
publishResults: 'false'
|
||||
platform: linux
|
||||
bicepIntegration: 'true'
|
||||
|
||||
- template: jobs/test.yaml
|
||||
parameters:
|
||||
name: macOS_10_15
|
||||
displayName: 'PowerShell 7.1 - macOS-10.15'
|
||||
imageName: 'macOS-10.15'
|
||||
platform: macos
|
||||
|
||||
- template: jobs/test.yaml
|
||||
parameters:
|
||||
name: windows
|
||||
displayName: 'PowerShell 5.1 - win2016'
|
||||
imageName: 'vs2017-win2016'
|
||||
platform: windows
|
||||
|
||||
- template: jobs/testContainer.yaml
|
||||
parameters:
|
||||
|
|
|
@ -8,6 +8,8 @@ parameters:
|
|||
imageName: ''
|
||||
coverage: 'false'
|
||||
publishResults: 'true'
|
||||
platform: 'linux'
|
||||
bicepIntegration: 'false'
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
|
@ -20,6 +22,10 @@ jobs:
|
|||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
|
||||
# - template: ../steps/installBicep.yaml
|
||||
# parameters:
|
||||
# platform: ${{ parameters.platform }}
|
||||
|
||||
# Install pipeline dependencies
|
||||
- powershell: ./.azure-pipelines/pipeline-deps.ps1
|
||||
displayName: 'Install dependencies'
|
||||
|
@ -35,6 +41,7 @@ jobs:
|
|||
- powershell: Invoke-Build TestModule -Configuration ${{ parameters.buildConfiguration }} -Build $(Build.BuildNumber)
|
||||
env:
|
||||
COVERAGE: ${{ parameters.coverage }}
|
||||
RUN_BICEP_INTEGRATION: ${{ parameters.bicepIntegration }}
|
||||
displayName: 'Test module'
|
||||
|
||||
# Pester test results
|
||||
|
|
|
@ -27,6 +27,10 @@ jobs:
|
|||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
|
||||
# - template: ../steps/installBicep.yaml
|
||||
# parameters:
|
||||
# platform: linux
|
||||
|
||||
# Install pipeline dependencies
|
||||
- powershell: ./.azure-pipelines/pipeline-deps.ps1
|
||||
displayName: 'Install dependencies'
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
|
||||
parameters:
|
||||
- name: platform
|
||||
type: string
|
||||
default: linux
|
||||
|
||||
steps:
|
||||
|
||||
- ${{ if eq(parameters.platform, 'linux') }}:
|
||||
- script: |
|
||||
apt-get install sudo
|
||||
# Fetch the latest Bicep CLI binary
|
||||
curl -Lo bicep.bin https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64
|
||||
# Mark it as executable
|
||||
chmod +x ./bicep.bin
|
||||
# Add bicep to your PATH (requires admin)
|
||||
sudo mv ./bicep.bin /usr/local/bin/bicep
|
||||
displayName: 'Install Bicep'
|
||||
|
||||
- ${{ if eq(parameters.platform, 'macos') }}:
|
||||
- script: |
|
||||
# Fetch the latest Bicep CLI binary
|
||||
curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-osx-x64
|
||||
# Mark it as executable
|
||||
chmod +x ./bicep
|
||||
# Add Gatekeeper exception (requires admin)
|
||||
sudo spctl --add ./bicep
|
||||
# Add bicep to your PATH (requires admin)
|
||||
sudo mv ./bicep /usr/local/bin/bicep
|
||||
displayName: 'Install Bicep'
|
||||
|
||||
- ${{ if eq(parameters.platform, 'windows') }}:
|
||||
- pwsh: |
|
||||
# Create the install folder
|
||||
$installPath = "$env:USERPROFILE\.bicep"
|
||||
$installDir = New-Item -ItemType Directory -Path $installPath -Force
|
||||
$installDir.Attributes += 'Hidden'
|
||||
# Fetch the latest Bicep CLI binary
|
||||
(New-Object Net.WebClient).DownloadFile("https://github.com/Azure/bicep/releases/latest/download/bicep-win-x64.exe", "$installPath\bicep.exe")
|
||||
# Add bicep to your PATH
|
||||
$currentPath = (Get-Item -path "HKCU:\Environment" ).GetValue('Path', '', 'DoNotExpandEnvironmentNames')
|
||||
if (-not $currentPath.Contains("%USERPROFILE%\.bicep")) { setx PATH ($currentPath + ";%USERPROFILE%\.bicep") }
|
||||
if (-not $env:path.Contains($installPath)) { $env:path += ";$installPath" }
|
||||
displayName: 'Install Bicep'
|
|
@ -20,6 +20,7 @@
|
|||
"files.associations": {
|
||||
"**/.azure-pipelines/*.yaml": "azure-pipelines",
|
||||
"**/.azure-pipelines/jobs/*.yaml": "azure-pipelines",
|
||||
"**/.azure-pipelines/steps/*.yaml": "azure-pipelines",
|
||||
"**/tests/**/Resources*.Template*.json": "arm-template"
|
||||
},
|
||||
"cSpell.words": [
|
||||
|
|
|
@ -7,6 +7,14 @@ See [troubleshooting guide] for a workaround to this issue.
|
|||
|
||||
## Unreleased
|
||||
|
||||
What's changed since pre-release v1.6.0-B2107028:
|
||||
|
||||
- New features:
|
||||
- **Experimental**: Added support for expansion from Bicep source files. [#848](https://github.com/Azure/PSRule.Rules.Azure/issues/848) [#670](https://github.com/Azure/PSRule.Rules.Azure/issues/670)
|
||||
- Bicep support is currently experimental.
|
||||
- To opt-in set the `AZURE_BICEP_FILE_EXPANSION` configuration to `true`.
|
||||
- For more information see [Using Bicep](https://azure.github.io/PSRule.Rules.Azure/using-bicep/).
|
||||
|
||||
## v1.6.0-B2107028 (pre-release)
|
||||
|
||||
What's changed since v1.5.1:
|
||||
|
|
|
@ -16,3 +16,22 @@
|
|||
--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);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ Configuration options for PSRule for Azure are set within the `ps-rule.yaml` fil
|
|||
|
||||
### Expand template parameter files
|
||||
|
||||
[:octicons-book-24: Docs][1]
|
||||
|
||||
PSRule for Azure can automatically expand Azure template parameter files.
|
||||
When enabled, PSRule for Azure automatically resolves parameter and template file context at runtime.
|
||||
|
||||
|
@ -67,6 +69,26 @@ configuration:
|
|||
AZURE_PARAMETER_FILE_EXPANSION: true
|
||||
```
|
||||
|
||||
[1]: setup/configuring-expansion.md#parameterfileexpansion
|
||||
|
||||
### Expand Bicep source files
|
||||
|
||||
[:octicons-book-24: Docs][2]
|
||||
|
||||
PSRule for Azure can automatically expand Bicep source files.
|
||||
When enabled, PSRule for Azure automatically expands and analyzes Azure resource from `.bicep` files.
|
||||
|
||||
To enabled this feature, set the `Configuration.AZURE_BICEP_FILE_EXPANSION` to `true`.
|
||||
This option can be set within the `ps-rule.yaml` file.
|
||||
|
||||
```yaml
|
||||
configuration:
|
||||
# Enable automatic expansion of bicep source files
|
||||
AZURE_BICEP_FILE_EXPANSION: true
|
||||
```
|
||||
|
||||
[2]: setup/configuring-expansion.md#bicepsourceexpansion
|
||||
|
||||
### Ignoring rules
|
||||
|
||||
To prevent a rule executing you can either:
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
|
||||
// Bicep documentation examples
|
||||
|
||||
@description('The location resources will be deployed.')
|
||||
param location string = resourceGroup().location
|
||||
|
||||
// An example NSG with a single rule to deny outbound management traffic
|
||||
resource nsg 'Microsoft.Network/networkSecurityGroups@2021-02-01' = {
|
||||
name: 'nsg-001'
|
||||
location: location
|
||||
properties: {
|
||||
securityRules: [
|
||||
{
|
||||
|
@ -30,6 +34,7 @@ resource nsg 'Microsoft.Network/networkSecurityGroups@2021-02-01' = {
|
|||
// An example App Gateway v2 with WAF enabled
|
||||
resource appGw 'Microsoft.Network/applicationGateways@2021-02-01' = {
|
||||
name: 'appGw-001'
|
||||
location: location
|
||||
properties: {
|
||||
sku: {
|
||||
name: 'WAF_v2'
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"metadata": {
|
||||
"_generator": {
|
||||
"name": "bicep",
|
||||
"version": "0.4.412.5873",
|
||||
"templateHash": "1973047202237601172"
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"defaultValue": "[resourceGroup().location]",
|
||||
"metadata": {
|
||||
"description": "The location resources will be deployed."
|
||||
}
|
||||
}
|
||||
},
|
||||
"functions": [],
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Network/networkSecurityGroups",
|
||||
"apiVersion": "2021-02-01",
|
||||
"name": "nsg-001",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"securityRules": [
|
||||
{
|
||||
"name": "deny-hop-outbound",
|
||||
"properties": {
|
||||
"priority": 200,
|
||||
"access": "Deny",
|
||||
"protocol": "Tcp",
|
||||
"direction": "Outbound",
|
||||
"sourceAddressPrefix": "VirtualNetwork",
|
||||
"destinationAddressPrefix": "*",
|
||||
"destinationPortRanges": [
|
||||
"3389",
|
||||
"22"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Network/applicationGateways",
|
||||
"apiVersion": "2021-02-01",
|
||||
"name": "appGw-001",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"sku": {
|
||||
"name": "WAF_v2",
|
||||
"tier": "WAF_v2"
|
||||
},
|
||||
"webApplicationFirewallConfiguration": {
|
||||
"enabled": true,
|
||||
"firewallMode": "Prevention",
|
||||
"ruleSetType": "OWASP",
|
||||
"ruleSetVersion": "3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -25,8 +25,9 @@ PSRule for Azure supports two methods for analyzing Azure resources:
|
|||
- Implement checks within Pull Requests (PRs).
|
||||
- Improve alignment of resources to WAF recommendations.
|
||||
- Identify issues that prevent successful resource deployments on Azure.
|
||||
- Integrate continual improvement and standardization of Azure resource configurations.
|
||||
- Implement release gates between environments.
|
||||
- **In-flight** — After resource are deployed to an Azure subscription.
|
||||
- **In-flight** — After resources are deployed to an Azure subscription.
|
||||
Use _in-flight_ analysis to:
|
||||
- Implement release gates between environments for non-native tools such as Terraform.
|
||||
- Performing offline analysis in split-environments.
|
||||
|
|
|
@ -139,16 +139,18 @@ This build script will compile the module and documentation then output the resu
|
|||
|
||||
#### Development dependencies
|
||||
|
||||
The following PowerShell modules will be automatically install if the required versions are not present:
|
||||
The following dependencies will be automatically installed if the required versions are not present:
|
||||
|
||||
- PlatyPS
|
||||
- Pester
|
||||
- PSScriptAnalyzer
|
||||
- PowerShellGet
|
||||
- PackageManagement
|
||||
- InvokeBuild
|
||||
- PowerShell modules:
|
||||
- PlatyPS
|
||||
- Pester
|
||||
- PSScriptAnalyzer
|
||||
- PowerShellGet
|
||||
- PackageManagement
|
||||
- InvokeBuild
|
||||
- Bicep CLI
|
||||
|
||||
These additional modules are only required for building PSRule for Azure.
|
||||
These dependencies are only required for building and running tests for PSRule for Azure.
|
||||
|
||||
Additionally .NET Core SDK v3.1 is required.
|
||||
.NET Core will not be automatically downloaded and installed.
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Configuring expansion
|
||||
|
||||
PSRule for Azure can automatically resolve template and parameter file context at runtime.
|
||||
PSRule for Azure can automatically resolve Azure resource context at runtime from infrastructure code.
|
||||
This feature can be enabled by using the following configuration options.
|
||||
|
||||
## Configuration
|
||||
|
@ -43,6 +47,38 @@ configuration:
|
|||
AZURE_PARAMETER_FILE_EXPANSION: true
|
||||
```
|
||||
|
||||
### Bicep source expansion
|
||||
|
||||
:octicons-milestone-24: v1.6.0 · :octicons-beaker-24: Experimental
|
||||
|
||||
This configuration option determines if Azure Bicep source files will automatically be expanded.
|
||||
By default, Bicep files will not be automatically expanded.
|
||||
|
||||
Bicep files are expanded when PSRule cmdlets with the `-Format File` parameter are used.
|
||||
|
||||
Syntax:
|
||||
|
||||
```yaml
|
||||
configuration:
|
||||
AZURE_BICEP_FILE_EXPANSION: bool
|
||||
```
|
||||
|
||||
Default:
|
||||
|
||||
```yaml
|
||||
# YAML: The default AZURE_BICEP_FILE_EXPANSION configuration option
|
||||
configuration:
|
||||
AZURE_BICEP_FILE_EXPANSION: false
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
# YAML: Set the AZURE_BICEP_FILE_EXPANSION configuration option to enable expansion
|
||||
configuration:
|
||||
AZURE_BICEP_FILE_EXPANSION: true
|
||||
```
|
||||
|
||||
### Deployment resource group
|
||||
|
||||
:octicons-milestone-24: v1.1.0
|
||||
|
@ -129,4 +165,3 @@ Example:
|
|||
AZURE_SUBSCRIPTION:
|
||||
displayName: 'My test subscription'
|
||||
```
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Configuring options
|
||||
|
||||
PSRule for Azure comes with many configuration options.
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Configuring rule defaults
|
||||
|
||||
PSRule for Azure include several rules that can be configured.
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Setup Bicep
|
||||
|
||||
To expand Azure resources for analysis from Bicep source files the Bicep CLI is required.
|
||||
The Bicep CLI is already installed on hosted runners and agents used by GitHub Action and Azure Pipelines.
|
||||
|
||||
!!! Abstract
|
||||
This topic covers setting up support for analyzing Azure resources within Bicep source file.
|
||||
|
||||
## Installing Bicep CLI
|
||||
|
||||
PSRule for Azure requires a minimum of Bicep CLI version **0.4.451**.
|
||||
|
||||
You may need to install or upgrade the Bicep CLI in the following scenarios:
|
||||
|
||||
- Your Bicep source files require a newer version of the CLI then supported by hosted agents.
|
||||
The Bicep CLI version can be found in the [included software][1] list for each supported platform.
|
||||
- You are using self-hosted runners with your GitHub Actions workflow.
|
||||
- You are using self-hosted agents with Azure Pipelines.
|
||||
- You are performing local validation or using a different CI platform.
|
||||
|
||||
The Bicep CLI can be installed on MacOS, Linux, and Windows.
|
||||
For installation instructions see [Setup your Bicep development environment][2].
|
||||
|
||||
[1]: https://github.com/actions/virtual-environments
|
||||
[2]: https://github.com/Azure/bicep/blob/main/docs/installing.md
|
||||
|
||||
!!! Tip
|
||||
When installing Bicep using the Azure CLI, Bicep is not added to the `PATH` environment variable.
|
||||
To use PSRule for Azure with the Azure CLI set the `PSRULE_AZURE_BICEP_USE_AZURE_CLI` to `true`.
|
||||
Setting this environment variable is explained in the next section.
|
||||
|
||||
## Setting environment variables
|
||||
|
||||
When expanding Bicep files, the path to the Bicep binary is required.
|
||||
By default, the `PATH` environment variable will be used to discover the binary path.
|
||||
When using this option, add the sub-directory containing the Bicep binary to the environment variable.
|
||||
|
||||
Alternatively, the path can be overridden by setting the `PSRULE_AZURE_BICEP_PATH` environment variable.
|
||||
When setting `PSRULE_AZURE_BICEP_PATH` specify the full path to the Bicep binary including the file name.
|
||||
File names used for Bicep binaries include `bicep`, or `bicep.exe`.
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
# Bash: Setting environment variable
|
||||
export PSRULE_AZURE_BICEP_PATH='/usr/local/bin/bicep'
|
||||
```
|
||||
|
||||
```powershell
|
||||
# PowerShell: Setting environment variable
|
||||
$Env:PSRULE_AZURE_BICEP_PATH = '/usr/local/bin/bicep';
|
||||
```
|
||||
|
||||
```yaml
|
||||
# GitHub Actions: Setting environment variable
|
||||
env:
|
||||
PSRULE_AZURE_BICEP_PATH: '/usr/local/bin/bicep'
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Azure Pipelines: Setting environment variable
|
||||
variables:
|
||||
- name: PSRULE_AZURE_BICEP_PATH
|
||||
value: '/usr/local/bin/bicep'
|
||||
```
|
||||
|
||||
### Using Azure CLI
|
||||
|
||||
By default, PSRule for Azure uses the Bicep CLI directly.
|
||||
An additional option is to use the Azure CLI to invoke the Bicep CLI.
|
||||
When using this option the required version of the CLI must be installed prior to using PSRule for Azure.
|
||||
This is explained in [Setup your Bicep development environment][3].
|
||||
|
||||
To enable this option, set the `PSRULE_AZURE_BICEP_USE_AZURE_CLI` environment variable to `true`.
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
# Bash: Setting environment variable
|
||||
export PSRULE_AZURE_BICEP_USE_AZURE_CLI=true
|
||||
```
|
||||
|
||||
```powershell
|
||||
# PowerShell: Setting environment variable
|
||||
$Env:PSRULE_AZURE_BICEP_USE_AZURE_CLI = 'true'
|
||||
```
|
||||
|
||||
```yaml
|
||||
# GitHub Actions: Setting environment variable
|
||||
env:
|
||||
PSRULE_AZURE_BICEP_USE_AZURE_CLI: true
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Azure Pipelines: Setting environment variable
|
||||
variables:
|
||||
- name: PSRULE_AZURE_BICEP_USE_AZURE_CLI
|
||||
value: true
|
||||
```
|
||||
|
||||
[3]: https://github.com/Azure/bicep/blob/main/docs/installing.md#install-and-manage-via-azure-cli-easiest
|
||||
|
||||
### Additional arguments
|
||||
|
||||
For configuration, additional arguments can be passed to the Bicep CLI.
|
||||
This is intended to improve forward compatibility with Bicep CLI.
|
||||
|
||||
To configure additional arguments, set the `PSRULE_AZURE_BICEP_ARGS` environment variable.
|
||||
|
||||
## Configuring expansion
|
||||
|
||||
[:octicons-book-24: Docs][4] · :octicons-beaker-24: Experimental
|
||||
|
||||
PSRule for Azure can automatically expand Bicep source files.
|
||||
When enabled, PSRule for Azure automatically expands and analyzes Azure resource from `.bicep` files.
|
||||
|
||||
To enabled this feature, set the `Configuration.AZURE_BICEP_FILE_EXPANSION` to `true`.
|
||||
This option can be set within the `ps-rule.yaml` file.
|
||||
|
||||
```yaml
|
||||
configuration:
|
||||
# Enable automatic expansion of bicep source files
|
||||
AZURE_BICEP_FILE_EXPANSION: true
|
||||
```
|
||||
|
||||
[4]]: configuring-expansion.md#bicepsourceexpansion
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Using Bicep source
|
||||
|
||||
PSRule for Azure also supports analyzing Azure resources contained within Bicep source files.
|
||||
|
||||
!!! Experimental
|
||||
Support for Bicep source files is currently an experimental feature.
|
||||
It is not recommended for production use.
|
||||
Please give us [feedback] on this feature and report any [issues] you encounter.
|
||||
|
||||
!!! Abstract
|
||||
This topic covers how to use use PSRule for Azure to validate Azure resources within Bicep source.
|
||||
|
||||
## Source file expansion
|
||||
|
||||
Bicep source files provide an additional option to define Azure resources.
|
||||
Bicep provides a abstraction layer on top of Azure Resource Manager (ARM) that is more human readable.
|
||||
When Azure resources are built from Bicep source files, an ARM template is generated.
|
||||
PSRule for Azure automates this in memory to allow analysis of Azure resources from `.bicep` files.
|
||||
|
||||
### Feature support
|
||||
|
||||
Expansion of Azure resources contained within Bicep source files is supported.
|
||||
For details on how this works and limitations see [Using templates][1].
|
||||
|
||||
In addition, currently the following limitation apply to using Bicep source files:
|
||||
|
||||
- The Bicep CLI must be installed.
|
||||
- PSRule for Azure will only expand Bicep source files without mandatory parameters.
|
||||
|
||||
[1]: using-templates.md#featuresupport
|
||||
|
||||
### Setup Bicep
|
||||
|
||||
To expand Azure resources for analysis from Bicep source files the Bicep CLI is required.
|
||||
For details on how to configure Bicep for PSRule for Azure see [Setup Bicep][2].
|
||||
|
||||
[2]: setup/setup-bicep.md
|
||||
|
||||
*[WAF]: Well-Architected Framework
|
||||
*[ARM]: Azure Resource Manager
|
||||
|
||||
[feedback]: https://github.com/Azure/PSRule.Rules.Azure/discussions
|
||||
[issues]: https://github.com/Azure/PSRule.Rules.Azure/issues
|
|
@ -2,13 +2,13 @@
|
|||
author: BernieWhite
|
||||
---
|
||||
|
||||
# Using metadata
|
||||
# Using templates
|
||||
|
||||
PSRule for Azure detects Azure template and parameter files in your repository based on their schemas.
|
||||
This provides template and parameter file linting for structure and general usage.
|
||||
|
||||
!!! Abstract
|
||||
This topic covers how to use metadata to improve the success of Azure deployments.
|
||||
This topic covers how to use Azure templates and metadata to improve the success of Azure deployments.
|
||||
|
||||
## Parameter file expansion
|
||||
|
||||
|
@ -16,14 +16,15 @@ In additional to template and parameter file linting,
|
|||
PSRule for Azure can automatically resolve template and parameter file context at runtime.
|
||||
Resolved context provides some unique benefits such as:
|
||||
|
||||
- **As deployed** — Analysis of Azure resources as if they are deployed.
|
||||
- **Improve success** — Templates are resolved before deployment.
|
||||
- Detect issues with invalid resource names, missing parameters, and JSON structure.
|
||||
- Increases success of deployments by finding errors earlier such as within a PR.
|
||||
- **As deployed** — Analysis of Azure resources against Azure WAF as if they are deployed.
|
||||
- Parameters, conditional resources, functions (built-in and user defined), variables,
|
||||
and copy loops are resolved.
|
||||
- Azure resource names are shown in passing and failing results.
|
||||
Resolving issues with resource configurations can be targeted by resource.
|
||||
- Resource file locations for template and parameter files are included in results.
|
||||
- **Unassigned parameters** — Detection of missing mandatory parameters.
|
||||
- Increases success of deployments by finding these errors earlier such as within a PR.
|
||||
- **Suppression by resource name** — Azure resource names can be used to apply exceptions.
|
||||
- Suppression allows for individual resources to be excluded from rules by name.
|
||||
|
||||
|
@ -35,6 +36,45 @@ PSRule for Azure uses links to achieve this.
|
|||
It is not enabled by default to preserve the default behavior prior to PSRule for Azure v1.4.0.
|
||||
[Creating your pipeline][1] covers how to enable this in a CI pipeline.
|
||||
|
||||
### Feature support
|
||||
|
||||
Expansion of Azure template parameter files works with Azure Resource Manager (ARM) features.
|
||||
By default this is an offline process, requiring no connectivity to Azure.
|
||||
Some functions that may be included in templates dynamically query Azure for current state.
|
||||
For these functions standard placeholder values are used by default.
|
||||
Functions that use placeholders include `reference`, `list*`.
|
||||
|
||||
The `subscription()` function will return the following unless overridden:
|
||||
|
||||
- subscriptionId: 'ffffffff-ffff-ffff-ffff-ffffffffffff'
|
||||
- tenantId: 'ffffffff-ffff-ffff-ffff-ffffffffffff'
|
||||
- displayName: 'PSRule Test Subscription'
|
||||
- state: 'NotDefined'
|
||||
|
||||
The `resourceGroup()` function will return the following unless overridden:
|
||||
|
||||
- name: 'ps-rule-test-rg'
|
||||
- location: 'eastus'
|
||||
- tags: { }
|
||||
- properties:
|
||||
- provisioningState: 'Succeeded'
|
||||
|
||||
To override, set the `AZURE_SUBSCRIPTION` and `AZURE_RESOURCE_GROUP` in configuration.
|
||||
|
||||
Currently the following limitations apply:
|
||||
|
||||
- Nested templates are expanded, external templates are not.
|
||||
- Deployment resources that link to an external template are returned as a resource.
|
||||
- Sub-resources such as diagnostic logs or configurations are automatically nested.
|
||||
Automatic nesting a sub-resource requires:
|
||||
- The parent resource is defined in the same template.
|
||||
- The sub-resource depends on the parent resource.
|
||||
- The `pickZones` template function is not supported.
|
||||
- The `environment` template function always returns values for Azure public cloud.
|
||||
- References to Key Vault secrets are not expanded.
|
||||
A placeholder value is used instead.
|
||||
- Multi-line strings are not supported.
|
||||
|
||||
## Template links
|
||||
|
||||
PSRule for Azure automatically detects parameter files and uses the following logic to associate templates.
|
||||
|
@ -112,7 +152,9 @@ When linking using naming convention, the template and the parameter file must b
|
|||
!!! Example
|
||||
A parameter file named `azuredeploy.parameters.json` links to the template file named `azuredeploy.json`.
|
||||
|
||||
[1]: creating-your-pipeline.md#expandtemplateparameterfiles
|
||||
|
||||
*[WAF]: Well-Architected Framework
|
||||
*[ARM]: Azure Resource Manager
|
||||
*[CI]: continuous integration
|
||||
*[PR]: Pull Request
|
||||
|
||||
[1]: creating-your-pipeline.md#expandtemplateparameterfiles
|
|
@ -8,13 +8,15 @@ While preparing infrastructure code artifacts, Azure resources can be validated
|
|||
PSRule for Azure can be installed locally on MacOS, Linux, and Windows for local validation.
|
||||
|
||||
!!! Tip
|
||||
If you haven't already, follow the instructions on [installing locally][1] before continuing.
|
||||
If you haven't already, follow the instructions on [Installing locally][1] before continuing.
|
||||
If analyzing Azure resources from Bicep source files, complete [Setup Bicep][2].
|
||||
|
||||
[1]: install-instructions.md#installinglocally
|
||||
[2]: setup/setup-bicep.md
|
||||
|
||||
## With Visual Studio Code
|
||||
|
||||
[:octicons-download-24: Extension][2]
|
||||
[:octicons-download-24: Extension][3]
|
||||
|
||||
An extension for Visual Studio Code is available for an integrated experience using PSRule for Azure.
|
||||
The Visual Studio Code extension includes a built-in `PSRule: Run analysis` task.
|
||||
|
@ -69,5 +71,5 @@ To use PSRule for Azure with the built-in `PSRule: Run analysis` task, insert th
|
|||
}
|
||||
```
|
||||
|
||||
[2]: https://marketplace.visualstudio.com/items?itemName=bewhite.psrule-vscode
|
||||
[3]: https://code.visualstudio.com/docs/editor/tasks
|
||||
[3]: https://marketplace.visualstudio.com/items?itemName=bewhite.psrule-vscode
|
||||
[4]: https://code.visualstudio.com/docs/editor/tasks
|
||||
|
|
14
mkdocs.yml
14
mkdocs.yml
|
@ -1,3 +1,6 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
site_name: PSRule for Azure
|
||||
site_url: https://azure.github.io/PSRule.Rules.Azure
|
||||
site_description: Ready to go validation and governance controls for Azure Infrastructure as Code (IaC).
|
||||
|
@ -9,13 +12,9 @@ edit_uri: blob/main/docs/
|
|||
repo_issue: https://github.com/Azure/PSRule.Rules.Azure/issues
|
||||
repo_discussion: https://github.com/Azure/PSRule.Rules.Azure/discussions
|
||||
|
||||
# copyright: MIT License - Copyright © Microsoft Corporation
|
||||
extra_css:
|
||||
- assets/stylesheets/extra.css
|
||||
|
||||
# extra_templates:
|
||||
# - home.html
|
||||
|
||||
theme:
|
||||
language: en
|
||||
name: material
|
||||
|
@ -41,7 +40,8 @@ nav:
|
|||
- Getting started:
|
||||
- Overview: features.md
|
||||
- Installation: install-instructions.md
|
||||
- Using metadata: using-metadata.md
|
||||
- Using templates: using-templates.md
|
||||
- Using Bicep source: using-bicep.md
|
||||
- Creating your pipeline: creating-your-pipeline.md
|
||||
- Validating locally: validating-locally.md
|
||||
- Customization:
|
||||
|
@ -61,6 +61,7 @@ nav:
|
|||
- Configuring options: setup/configuring-options.md
|
||||
- Configuring rule defaults: setup/configuring-rules.md
|
||||
- Configuring expansion: setup/configuring-expansion.md
|
||||
- Setup Bicep: setup/setup-bicep.md
|
||||
- Reference:
|
||||
- By pillar: en/rules/module.md
|
||||
- By resource: en/rules/resource.md
|
||||
|
@ -95,6 +96,9 @@ plugins:
|
|||
on_nav: "docs.hooks:build_reference_nav"
|
||||
- search
|
||||
- git-revision-date
|
||||
- redirects:
|
||||
redirect_maps:
|
||||
'using-metadata.md': 'using-templates.md'
|
||||
|
||||
extra:
|
||||
version:
|
||||
|
|
|
@ -260,7 +260,7 @@ task CopyModule MinifyData, {
|
|||
# Synopsis: Build modules only
|
||||
task BuildModule BuildDotNet, CopyModule
|
||||
|
||||
task TestModule ModuleDependencies, Pester, PSScriptAnalyzer, {
|
||||
task TestModule ModuleDependencies, Pester, PSScriptAnalyzer, BicepIntegrationTests, {
|
||||
# Run Pester tests
|
||||
$pesterParams = @{ Path = (Join-Path -Path $PWD -ChildPath tests/PSRule.Rules.Azure.Tests); OutputFile = 'reports/pester-unit.xml'; OutputFormat = 'NUnitXml'; PesterOption = @{ IncludeVSCodeMarker = $True }; PassThru = $True; };
|
||||
|
||||
|
@ -307,6 +307,27 @@ task IntegrationTest ModuleDependencies, Pester, PSScriptAnalyzer, {
|
|||
}
|
||||
}
|
||||
|
||||
task BicepIntegrationTests {
|
||||
if ($Env:RUN_BICEP_INTEGRATION -eq 'true') {
|
||||
# Run Pester tests
|
||||
$pesterParams = @{ Path = (Join-Path -Path $PWD -ChildPath tests/Bicep); OutputFile = 'reports/bicep-integration.xml'; OutputFormat = 'NUnitXml'; PesterOption = @{ IncludeVSCodeMarker = $True }; PassThru = $True; };
|
||||
|
||||
if (!(Test-Path -Path reports)) {
|
||||
$Null = New-Item -Path reports -ItemType Directory -Force;
|
||||
}
|
||||
|
||||
$results = Invoke-Pester @pesterParams;
|
||||
|
||||
# Throw an error if pester tests failed
|
||||
if ($Null -eq $results) {
|
||||
throw 'Failed to get Pester test results.';
|
||||
}
|
||||
elseif ($results.FailedCount -gt 0) {
|
||||
throw "$($results.FailedCount) tests failed.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Synopsis: Run validation
|
||||
task Rules PSRule, {
|
||||
$assertParams = @{
|
||||
|
|
|
@ -12,6 +12,12 @@ input:
|
|||
- '*.Designer.cs'
|
||||
- '*.resx'
|
||||
- '*.sln'
|
||||
- '*.txt'
|
||||
- '*.html'
|
||||
- '*.ico'
|
||||
|
||||
include:
|
||||
path: []
|
||||
|
||||
output:
|
||||
culture:
|
||||
|
|
|
@ -5,3 +5,4 @@ mike==1.0.1
|
|||
mkdocs-simple-hooks==0.1.3
|
||||
mkdocs-git-revision-date-plugin==0.3.1
|
||||
mdx-truly-sane-lists==1.2
|
||||
mkdocs-redirects==1.0.3
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
|
||||
namespace PSRule.Rules.Azure
|
||||
{
|
||||
internal sealed class EnvironmentHelper
|
||||
{
|
||||
public static readonly EnvironmentHelper Default = new EnvironmentHelper();
|
||||
|
||||
internal bool TryBool(string key, out bool value)
|
||||
{
|
||||
value = default;
|
||||
return TryVariable(key, out string variable) && TryParseBool(variable, out value);
|
||||
}
|
||||
|
||||
private bool TryVariable(string key, out string variable)
|
||||
{
|
||||
variable = Environment.GetEnvironmentVariable(key);
|
||||
return variable != null;
|
||||
}
|
||||
|
||||
private static bool TryParseBool(string variable, out bool value)
|
||||
{
|
||||
if (bool.TryParse(variable, out value))
|
||||
return true;
|
||||
|
||||
if (int.TryParse(variable, out int ivalue))
|
||||
{
|
||||
value = ivalue > 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSRule.Rules.Azure.Configuration;
|
||||
using PSRule.Rules.Azure.Data.Template;
|
||||
using PSRule.Rules.Azure.Pipeline;
|
||||
using PSRule.Rules.Azure.Resources;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Management.Automation;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace PSRule.Rules.Azure.Data.Bicep
|
||||
{
|
||||
internal sealed class BicepHelper
|
||||
{
|
||||
private static readonly char[] LINUX_PATH_ENV_SEPARATOR = new char[] { ':' };
|
||||
private static readonly char[] WINDOWS_PATH_ENV_SEPARATOR = new char[] { ';' };
|
||||
|
||||
private readonly PipelineContext Context;
|
||||
private readonly ResourceGroupOption _ResourceGroup;
|
||||
private readonly SubscriptionOption _Subscription;
|
||||
|
||||
public BicepHelper(PipelineContext context, ResourceGroupOption resourceGroup, SubscriptionOption subscription)
|
||||
{
|
||||
Context = context;
|
||||
_ResourceGroup = resourceGroup;
|
||||
_Subscription = subscription;
|
||||
}
|
||||
|
||||
internal PSObject[] ProcessFile(string sourcePath)
|
||||
{
|
||||
if (!File.Exists(sourcePath))
|
||||
throw new FileNotFoundException(string.Format(Thread.CurrentThread.CurrentCulture, PSRuleResources.TemplateFileNotFound, sourcePath), sourcePath);
|
||||
|
||||
var json = ReadFile(sourcePath);
|
||||
if (json == null)
|
||||
return Array.Empty<PSObject>();
|
||||
|
||||
return ProcessJson(json, sourcePath);
|
||||
}
|
||||
|
||||
internal PSObject[] ProcessJson(JObject templateObject, string sourcePath)
|
||||
{
|
||||
var visitor = new RuleDataExportVisitor();
|
||||
|
||||
// Load context
|
||||
var templateContext = new TemplateVisitor.TemplateContext(Context, _Subscription, _ResourceGroup);
|
||||
|
||||
// Process
|
||||
try
|
||||
{
|
||||
templateContext.SetSource(sourcePath, null);
|
||||
visitor.Visit(templateContext, "helper", templateObject);
|
||||
}
|
||||
catch (Exception inner)
|
||||
{
|
||||
throw new TemplateReadException(string.Format(Thread.CurrentThread.CurrentCulture, PSRuleResources.BicepExpandInvalid, sourcePath, inner.Message), inner, sourcePath, null);
|
||||
}
|
||||
|
||||
// Return results
|
||||
var results = new List<PSObject>();
|
||||
var serializer = new JsonSerializer();
|
||||
serializer.Converters.Add(new PSObjectJsonConverter());
|
||||
foreach (var resource in templateContext.GetResources())
|
||||
results.Add(resource.Value.ToObject<PSObject>(serializer));
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private JObject ReadFile(string path)
|
||||
{
|
||||
var bicep = GetBicep(path);
|
||||
if (bicep == null)
|
||||
throw new BicepCompileException(string.Format(Thread.CurrentThread.CurrentCulture, PSRuleResources.BicepNotFound), null, path);
|
||||
|
||||
try
|
||||
{
|
||||
if (!bicep.HasExited)
|
||||
bicep.WaitForExit();
|
||||
|
||||
if (bicep.ExitCode != 0)
|
||||
{
|
||||
var error = bicep.StandardError.ReadToEnd();
|
||||
throw new BicepCompileException(string.Format(Thread.CurrentThread.CurrentCulture, PSRuleResources.BicepCompileError, path, error), null, path);
|
||||
}
|
||||
|
||||
using (var reader = new JsonTextReader(bicep.StandardOutput))
|
||||
{
|
||||
return JObject.Load(reader);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bicep.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private Process GetBicep(string sourcePath)
|
||||
{
|
||||
var useAzCLI = false;
|
||||
if (!(TryBicepPath(out string binPath) || TryAzCLIPath(out binPath, out useAzCLI)) || string.IsNullOrEmpty(binPath))
|
||||
return null;
|
||||
|
||||
var args = GetBicepBuildArgs(sourcePath, useAzCLI);
|
||||
var startInfo = new ProcessStartInfo(binPath, args)
|
||||
{
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
WorkingDirectory = PSRuleOption.GetWorkingPath(),
|
||||
};
|
||||
//Context.Writer.WriteDebug(Diagnostics.DebugRunningBicep, binaryPath);
|
||||
var p = Process.Start(startInfo);
|
||||
return p;
|
||||
}
|
||||
|
||||
private static bool TryBicepPath(out string binPath)
|
||||
{
|
||||
if (TryBicepEnvVariable(out binPath))
|
||||
return true;
|
||||
|
||||
return TryBinaryPath(GetBicepBinaryName(), out binPath);
|
||||
}
|
||||
|
||||
private static bool TryAzCLIPath(out string binPath, out bool useAzCLI)
|
||||
{
|
||||
useAzCLI = false;
|
||||
binPath = null;
|
||||
if (!UseAzCLI())
|
||||
return false;
|
||||
|
||||
return TryBinaryPath(GetAzBinaryName(), out binPath);
|
||||
}
|
||||
|
||||
private static bool TryBinaryPath(string bin, out string binPath)
|
||||
{
|
||||
var paths = GetPathEnv();
|
||||
for (var i = 0; paths != null && i < paths.Length; i++)
|
||||
{
|
||||
binPath = Path.Combine(paths[i], bin);
|
||||
if (File.Exists(binPath))
|
||||
return true;
|
||||
}
|
||||
binPath = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string[] GetPathEnv()
|
||||
{
|
||||
var envPath = System.Environment.GetEnvironmentVariable("PATH");
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return envPath.Split(LINUX_PATH_ENV_SEPARATOR, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
return envPath.Split(WINDOWS_PATH_ENV_SEPARATOR, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
private static bool TryBicepEnvVariable(out string binaryPath)
|
||||
{
|
||||
binaryPath = System.Environment.GetEnvironmentVariable("PSRULE_AZURE_BICEP_PATH");
|
||||
return !string.IsNullOrEmpty(binaryPath);
|
||||
}
|
||||
|
||||
private static string GetBicepBinaryName()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return "bicep";
|
||||
|
||||
return "bicep.exe";
|
||||
}
|
||||
|
||||
private static string GetAzBinaryName()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return "az";
|
||||
|
||||
return "az.exe";
|
||||
}
|
||||
|
||||
private static string GetBicepBuildArgs(string sourcePath, bool useAzCLI)
|
||||
{
|
||||
GetBicepBuildAdditionalArgs(out string args);
|
||||
return string.Concat("build --stdout ", args, useAzCLI ? " --file" : string.Empty , " \"", sourcePath, "\"");
|
||||
|
||||
}
|
||||
|
||||
private static void GetBicepBuildAdditionalArgs(out string args)
|
||||
{
|
||||
args = System.Environment.GetEnvironmentVariable("PSRULE_AZURE_BICEP_ARGS") ?? string.Empty;
|
||||
}
|
||||
|
||||
private static bool UseAzCLI()
|
||||
{
|
||||
return EnvironmentHelper.Default.TryBool("PSRULE_AZURE_BICEP_USE_AZURE_CLI", out bool value) ? value : false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -117,8 +117,14 @@ namespace PSRule.Rules.Azure.Pipeline
|
|||
private TemplateReadException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context) { }
|
||||
|
||||
/// <summary>
|
||||
/// The file path to an Azure Template.
|
||||
/// </summary>
|
||||
public string TemplateFile { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The file path to an Azure Template parameter file.
|
||||
/// </summary>
|
||||
public string ParameterFile { get; }
|
||||
|
||||
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
||||
|
@ -171,4 +177,44 @@ namespace PSRule.Rules.Azure.Pipeline
|
|||
base.GetObjectData(info, context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An exception related to compiling Bicep source files.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class BicepCompileException : PipelineException
|
||||
{
|
||||
public BicepCompileException()
|
||||
{
|
||||
}
|
||||
|
||||
public BicepCompileException(string message)
|
||||
: base(message) { }
|
||||
|
||||
public BicepCompileException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
|
||||
internal BicepCompileException(string message, Exception innerException, string sourceFile)
|
||||
: base(message, innerException)
|
||||
{
|
||||
SourceFile = sourceFile;
|
||||
}
|
||||
|
||||
private BicepCompileException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context) { }
|
||||
|
||||
/// <summary>
|
||||
/// The file path to an Azure Bicep source file.
|
||||
/// </summary>
|
||||
public string SourceFile { get; }
|
||||
|
||||
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
|
||||
base.GetObjectData(info, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,12 @@ namespace PSRule.Rules.Azure.Pipeline.Output
|
|||
internal PSPipelineWriter(PSRuleOption option)
|
||||
: base(null, option) { }
|
||||
|
||||
internal PSPipelineWriter(PSRuleOption option, PSCmdlet commandRuntime)
|
||||
: base(null, option)
|
||||
{
|
||||
UseCommandRuntime(commandRuntime);
|
||||
}
|
||||
|
||||
internal void UseCommandRuntime(PSCmdlet commandRuntime)
|
||||
{
|
||||
if (commandRuntime == null)
|
||||
|
|
|
@ -60,6 +60,15 @@ namespace PSRule.Rules.Azure.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Running bicep from '{0}'..
|
||||
/// </summary>
|
||||
internal static string DebugRunningBicep {
|
||||
get {
|
||||
return ResourceManager.GetString("DebugRunningBicep", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Searching for files in '{0}'..
|
||||
/// </summary>
|
||||
|
|
|
@ -117,6 +117,9 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="DebugRunningBicep" xml:space="preserve">
|
||||
<value>Running bicep from '{0}'.</value>
|
||||
</data>
|
||||
<data name="VerboseFindFiles" xml:space="preserve">
|
||||
<value>Searching for files in '{0}'.</value>
|
||||
</data>
|
||||
|
|
|
@ -114,6 +114,33 @@ namespace PSRule.Rules.Azure.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bicep compilation of '{0}' failed with: {1}.
|
||||
/// </summary>
|
||||
internal static string BicepCompileError {
|
||||
get {
|
||||
return ResourceManager.GetString("BicepCompileError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unable to expand resources because the source file '{0}' was not valid. {1}.
|
||||
/// </summary>
|
||||
internal static string BicepExpandInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("BicepExpandInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bicep CLI can not be found. Consider installing Bicep or setting the PSRULE_AZURE_BICEP_PATH environment variable to resolve this issue..
|
||||
/// </summary>
|
||||
internal static string BicepNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("BicepNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occured evaluating expression '{0}' line {1}. {2}.
|
||||
/// </summary>
|
||||
|
|
|
@ -135,6 +135,15 @@
|
|||
<data name="ArgumentsOutOfRange" xml:space="preserve">
|
||||
<value>The number of arguments '{1}' is not within the allowed range for '{0}'.</value>
|
||||
</data>
|
||||
<data name="BicepCompileError" xml:space="preserve">
|
||||
<value>Bicep compilation of '{0}' failed with: {1}</value>
|
||||
</data>
|
||||
<data name="BicepExpandInvalid" xml:space="preserve">
|
||||
<value>Unable to expand resources because the source file '{0}' was not valid. {1}</value>
|
||||
</data>
|
||||
<data name="BicepNotFound" xml:space="preserve">
|
||||
<value>Bicep CLI can not be found. Consider installing Bicep or setting the PSRULE_AZURE_BICEP_PATH environment variable to resolve this issue.</value>
|
||||
</data>
|
||||
<data name="ExpressionEvaluateError" xml:space="preserve">
|
||||
<value>An error occured evaluating expression '{0}' line {1}. {2}</value>
|
||||
</data>
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using PSRule.Rules.Azure.Configuration;
|
||||
using PSRule.Rules.Azure.Data.Bicep;
|
||||
using PSRule.Rules.Azure.Data.Network;
|
||||
using PSRule.Rules.Azure.Data.Template;
|
||||
using PSRule.Rules.Azure.Pipeline;
|
||||
using System;
|
||||
using PSRule.Rules.Azure.Pipeline.Output;
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace PSRule.Rules.Azure.Runtime
|
||||
|
@ -31,7 +32,6 @@ namespace PSRule.Rules.Azure.Runtime
|
|||
public static PSObject[] GetResources(string parameterFile)
|
||||
{
|
||||
var context = GetContext();
|
||||
|
||||
var linkHelper = new TemplateLinkHelper(context, PSRuleOption.GetWorkingPath(), true);
|
||||
var link = linkHelper.ProcessParameterFile(parameterFile);
|
||||
if (link == null)
|
||||
|
@ -41,6 +41,13 @@ namespace PSRule.Rules.Azure.Runtime
|
|||
return helper.ProcessTemplate(link.TemplateFile, link.ParameterFile, out _);
|
||||
}
|
||||
|
||||
public static PSObject[] GetBicepResources(string bicepFile, PSCmdlet commandRuntime)
|
||||
{
|
||||
var context = GetContext(commandRuntime);
|
||||
var bicep = new BicepHelper(context, context.Option.Configuration.ResourceGroup, context.Option.Configuration.Subscription);
|
||||
return bicep.ProcessFile(bicepFile);
|
||||
}
|
||||
|
||||
public static INetworkSecurityGroupEvaluator GetNetworkSecurityGroup(PSObject[] securityRules)
|
||||
{
|
||||
var builder = new NetworkSecurityGroupEvaluator();
|
||||
|
@ -50,10 +57,10 @@ namespace PSRule.Rules.Azure.Runtime
|
|||
|
||||
#region Helper methods
|
||||
|
||||
private static PipelineContext GetContext()
|
||||
private static PipelineContext GetContext(PSCmdlet commandRuntime = null)
|
||||
{
|
||||
var option = PSRuleOption.FromFileOrDefault(PSRuleOption.GetWorkingPath());
|
||||
var context = new PipelineContext(option, null);
|
||||
var context = new PipelineContext(option, commandRuntime != null ? new PSPipelineWriter(option, commandRuntime) : null);
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,11 @@ spec:
|
|||
resourceGroupName: [ 'ResourceGroupName' ]
|
||||
configuration:
|
||||
AZURE_PARAMETER_FILE_EXPANSION: false
|
||||
AZURE_BICEP_FILE_EXPANSION: false
|
||||
convention:
|
||||
include:
|
||||
- 'Azure.ExpandTemplate'
|
||||
- 'Azure.ExpandBicep'
|
||||
output:
|
||||
culture:
|
||||
- en
|
||||
|
|
|
@ -30,3 +30,26 @@ Export-PSRuleConvention 'Azure.ExpandTemplate' -If { $Configuration.AZURE_PARAME
|
|||
Write-Error -Message "Failed to expand parameter file '$($TargetObject.FullName)'. $($_.Exception.Message)" -ErrorId 'Azure.ExpandTemplate.ConventionException';
|
||||
}
|
||||
}
|
||||
|
||||
#region Bicep
|
||||
|
||||
Export-PSRuleConvention 'Azure.ExpandBicep' -If { $Configuration.AZURE_BICEP_FILE_EXPANSION -eq $True -and $TargetObject.Extension -eq '.bicep' } -Begin {
|
||||
Write-Verbose "[Azure.ExpandBicep] -- Expanding bicep source: $($TargetObject.FullName)";
|
||||
try {
|
||||
$data = [PSRule.Rules.Azure.Runtime.Helper]::GetBicepResources($TargetObject.FullName, $PSCmdlet);
|
||||
if ($Null -ne $data) {
|
||||
$PSRule.Import($data);
|
||||
}
|
||||
}
|
||||
catch [PSRule.Rules.Azure.Pipeline.BicepCompileException] {
|
||||
Write-Error -Exception $_.Exception;
|
||||
}
|
||||
catch [System.IO.FileNotFoundException] {
|
||||
Write-Error -Exception $_.Exception;
|
||||
}
|
||||
catch {
|
||||
Write-Error -Message "Failed to expand bicep source '$($TargetObject.FullName)'. $($_.Exception.Message)" -ErrorId 'Azure.ExpandBicep.ConventionException';
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Bicep
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
#
|
||||
# Unit tests for Azure conventions
|
||||
#
|
||||
|
||||
[CmdletBinding()]
|
||||
param ()
|
||||
|
||||
# Setup error handling
|
||||
$ErrorActionPreference = 'Stop';
|
||||
Set-StrictMode -Version latest;
|
||||
|
||||
if ($Env:SYSTEM_DEBUG -eq 'true') {
|
||||
$VerbosePreference = 'Continue';
|
||||
}
|
||||
|
||||
# Setup tests paths
|
||||
$rootPath = $PWD;
|
||||
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Azure) -Force;
|
||||
$here = (Resolve-Path $PSScriptRoot).Path;
|
||||
|
||||
Describe 'Bicep' -Tag 'Bicep' {
|
||||
Context 'Azure.ExpandBicep convention' {
|
||||
It 'Expands Bicep source files' {
|
||||
$invokeParams = @{
|
||||
Baseline = 'Azure.All'
|
||||
Module = 'PSRule.Rules.Azure'
|
||||
WarningAction = 'Ignore'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
|
||||
# Default
|
||||
$sourceFile = Join-Path -Path $rootPath -ChildPath 'docs/examples.bicep';
|
||||
$result = @(Invoke-PSRule @invokeParams -InputPath $sourceFile -Format File);
|
||||
$result | Should -BeNullOrEmpty;
|
||||
|
||||
# Expand source files
|
||||
$option = @{
|
||||
'Configuration.AZURE_BICEP_FILE_EXPANSION' = $True
|
||||
}
|
||||
$result = @(Invoke-PSRule @invokeParams -InputPath $sourceFile -Format File -Option $option);
|
||||
$result.Length | Should -BeGreaterThan 1;
|
||||
$resource = $result | Where-Object { $_.TargetType -eq 'Microsoft.Network/networkSecurityGroups' };
|
||||
$resource | Should -Not -BeNullOrEmpty;
|
||||
$resource.TargetName | Should -BeIn 'nsg-001'
|
||||
}
|
||||
|
||||
It 'Expands Bicep source files with Azure CLI' {
|
||||
$invokeParams = @{
|
||||
Baseline = 'Azure.All'
|
||||
Module = 'PSRule.Rules.Azure'
|
||||
WarningAction = 'Ignore'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
|
||||
# Default
|
||||
$sourceFile = Join-Path -Path $rootPath -ChildPath 'docs/examples.bicep';
|
||||
$result = @(Invoke-PSRule @invokeParams -InputPath $sourceFile -Format File);
|
||||
$result | Should -BeNullOrEmpty;
|
||||
|
||||
try {
|
||||
# Install CLI
|
||||
az bicep install
|
||||
|
||||
# Expand source files
|
||||
$option = @{
|
||||
'Configuration.AZURE_BICEP_FILE_EXPANSION' = $True
|
||||
}
|
||||
$Env:PSRULE_AZURE_BICEP_USE_AZURE_CLI = 'true';
|
||||
$result = @(Invoke-PSRule @invokeParams -InputPath $sourceFile -Format File -Option $option);
|
||||
$result.Length | Should -BeGreaterThan 1;
|
||||
$resource = $result | Where-Object { $_.TargetType -eq 'Microsoft.Network/networkSecurityGroups' };
|
||||
$resource | Should -Not -BeNullOrEmpty;
|
||||
$resource.TargetName | Should -BeIn 'nsg-001'
|
||||
}
|
||||
finally {
|
||||
Remove-Item 'Env:PSRULE_AZURE_BICEP_USE_AZURE_CLI' -Force;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче