From 2120863285f34162e90130a43570d81219f76b56 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Mon, 5 Sep 2022 08:36:37 +0100 Subject: [PATCH] Add PSRule To ALZ Bicep Testing (#313) * Initial PSRule without parameter files #206 (#207) * Initial PSRule without parameter files #206 * Update triggers and reference extension * Separate job to ignore build bicep code * Update PSRule options to include Bicep samples * PSRule baseline and minium samples (#236) * Update exclusions and complete AZ params for PIPs (#242) * Update exclusions and complete AZ params for PIPs * Add additional comments * Final updates for merge (#252) * psrule sample fixes * fix github linter for PSRule MD * typo fix * update rules Co-authored-by: Bernie White --- .github/workflows/bicep-build-to-validate.yml | 24 +++- .ps-rule/FalsePositiveNsgBastion.Rule.yaml | 25 ++++ .ps-rule/Minimum.Rule.yaml | 34 ++++++ .ps-rule/UnsupportedPipBastion.Rule.yaml | 25 ++++ .ps-rule/en/ALZ.MinimumSample.md | 15 +++ .vscode/bicep.code-snippets | 70 ++++++++++++ .vscode/extensions.json | 5 +- .vscode/tasks.json | 16 +++ docs/wiki/Contributing.md | 1 + .../samples/baseline.sample.bicep | 107 ++++++++++++++++++ .../samples/minimum.sample.bicep | 26 +++++ .../publicIp/samples/baseline.sample.bicep | 38 +++++++ .../publicIp/samples/minimum.sample.bicep | 33 ++++++ ps-rule.yaml | 71 ++++++++++++ 14 files changed, 487 insertions(+), 3 deletions(-) create mode 100644 .ps-rule/FalsePositiveNsgBastion.Rule.yaml create mode 100644 .ps-rule/Minimum.Rule.yaml create mode 100644 .ps-rule/UnsupportedPipBastion.Rule.yaml create mode 100644 .ps-rule/en/ALZ.MinimumSample.md create mode 100644 .vscode/bicep.code-snippets create mode 100644 .vscode/tasks.json create mode 100644 infra-as-code/bicep/modules/hubNetworking/samples/baseline.sample.bicep create mode 100644 infra-as-code/bicep/modules/hubNetworking/samples/minimum.sample.bicep create mode 100644 infra-as-code/bicep/modules/publicIp/samples/baseline.sample.bicep create mode 100644 infra-as-code/bicep/modules/publicIp/samples/minimum.sample.bicep create mode 100644 ps-rule.yaml diff --git a/.github/workflows/bicep-build-to-validate.yml b/.github/workflows/bicep-build-to-validate.yml index 0a624251c..070b74105 100644 --- a/.github/workflows/bicep-build-to-validate.yml +++ b/.github/workflows/bicep-build-to-validate.yml @@ -6,6 +6,8 @@ on: - main paths: - "**.bicep" + - "ps-rule.yaml" + - ".ps-rule/*" workflow_dispatch: {} jobs: @@ -15,7 +17,7 @@ jobs: steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 @@ -59,3 +61,23 @@ jobs: Write-Information "***** List of resource types in ALZ-Bicep modules *****" -InformationAction Continue $resourceTypesFullList.Keys | Sort-Object + + azure_waf: + name: Test Azure Well-Architected Framework + runs-on: ubuntu-latest + + steps: + + - name: Checkout Repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + # Add pipeline tests for Azure Well-Architected Framework. + # See https://aka.ms/ps-rule-action for configuration options. + - name: Run PSRule analysis + uses: Microsoft/ps-rule@v2.3.2 + with: + modules: PSRule.Rules.Azure + baseline: Azure.GA_2022_06 + continue-on-error: true diff --git a/.ps-rule/FalsePositiveNsgBastion.Rule.yaml b/.ps-rule/FalsePositiveNsgBastion.Rule.yaml new file mode 100644 index 000000000..efbab2dd6 --- /dev/null +++ b/.ps-rule/FalsePositiveNsgBastion.Rule.yaml @@ -0,0 +1,25 @@ +# +# Suppression and rules for unsupported scenarios. +# + +# NOTE: +# For details on authoring suppression groups see: +# https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_SuppressionGroups/ +# https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Expressions/ + +--- +# Synopsis: Ignore NSG lateral movement rule for Azure Bastion as this is needed for Bastion to work. +apiVersion: github.com/microsoft/PSRule/v1 +kind: SuppressionGroup +metadata: + name: ALZ.NSGForBastion +spec: + rule: + - Azure.NSG.LateralTraversal + if: + allOf: + - name: '.' + contains: bastion + - type: '.' + in: + - Microsoft.Network/networkSecurityGroups diff --git a/.ps-rule/Minimum.Rule.yaml b/.ps-rule/Minimum.Rule.yaml new file mode 100644 index 000000000..af5c2d71f --- /dev/null +++ b/.ps-rule/Minimum.Rule.yaml @@ -0,0 +1,34 @@ +# +# Suppression and rules for the minimum sample configuration. +# + +# NOTE: +# For details on authoring suppression groups see: +# https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_SuppressionGroups/ +# https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Expressions/ + +--- +# Synopsis: Ignore the minimum sample configuration. +apiVersion: github.com/microsoft/PSRule/v1 +kind: SuppressionGroup +metadata: + name: ALZ.MinimumSample +spec: + rule: + - Azure.Firewall.Mode + - Azure.VNG.VPNAvailabilityZoneSKU + - Azure.PublicIP.AvailabilityZone + - Azure.VNG.VPNActiveActive + - Azure.PublicIP.StandardSKU + - Azure.VNET.UseNSGs + if: + allOf: + - type: '.' + in: + - Microsoft.Network/azureFirewalls + - Microsoft.Network/publicIPAddresses + - Microsoft.Network/virtualNetworks + - Microsoft.Network/virtualNetworkGateways + - source: 'Template' + endsWith: + - 'minimum.sample.bicep' diff --git a/.ps-rule/UnsupportedPipBastion.Rule.yaml b/.ps-rule/UnsupportedPipBastion.Rule.yaml new file mode 100644 index 000000000..7cc38de4b --- /dev/null +++ b/.ps-rule/UnsupportedPipBastion.Rule.yaml @@ -0,0 +1,25 @@ +# +# Suppression and rules for unsupported scenarios. +# + +# NOTE: +# For details on authoring suppression groups see: +# https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_SuppressionGroups/ +# https://microsoft.github.io/PSRule/v2/concepts/PSRule/en-US/about_PSRule_Expressions/ + +--- +# Synopsis: Ignore availability zones for Azure Bastion public IP which is not supported. https://github.com/Azure/PSRule.Rules.Azure/issues/1442 +apiVersion: github.com/microsoft/PSRule/v1 +kind: SuppressionGroup +metadata: + name: ALZ.PublicIPForBastion +spec: + rule: + - Azure.PublicIP.AvailabilityZone + if: + allOf: + - name: '.' + contains: bastion + - type: '.' + in: + - Microsoft.Network/publicIPAddresses diff --git a/.ps-rule/en/ALZ.MinimumSample.md b/.ps-rule/en/ALZ.MinimumSample.md new file mode 100644 index 000000000..903c966c7 --- /dev/null +++ b/.ps-rule/en/ALZ.MinimumSample.md @@ -0,0 +1,15 @@ +# Ignore minimum sample + +## SYNOPSIS + +Ignore the minimum sample configuration that may not be WAF compliant. +See [https://github.com/Azure/ALZ-Bicep/blob/main/.ps-rule/en/ALZ.MinimumSample.md](https://github.com/Azure/ALZ-Bicep/blob/main/.ps-rule/en/ALZ.MinimumSample.md). + +## DESCRIPTION + +The _minimum_ sample provides a basic configuration. +It is typically less complex, and has requires fewer requirements. +This make is most suitable for early development and testing. + +The basic configuration may not have all the features required for alignment to the Well-Architected Framework. +Consider using the _baseline_ sample for enterprise environments. diff --git a/.vscode/bicep.code-snippets b/.vscode/bicep.code-snippets new file mode 100644 index 000000000..698c123dd --- /dev/null +++ b/.vscode/bicep.code-snippets @@ -0,0 +1,70 @@ +{ + "Bicep minimum sample": { + "scope": "bicep", + "prefix": "bicep-minimum-sample", + "description": "A minmum sample for testing and examples.", + "body": [ + "//", + "// Minimum deployment sample", + "//", + "", + "// Use this sample to deploy the minimum resource configuration.", + "", + "targetScope = 'resourceGroup'", + "", + "// ----------", + "// PARAMETERS", + "// ----------", + "", + "@description('The Azure location to deploy to.')", + "param location string = resourceGroup().location", + "", + "// ---------", + "// RESOURCES", + "// ---------", + "", + "@description('Minimum resource configuration')", + "module ${1} '../${2}}.bicep' = {", + " name: '${1}'", + " params: {", + " parLocation: location", + " parTags: {}", + " }", + "}" + ] + }, + "Bicep baseline sample": { + "scope": "bicep", + "prefix": "bicep-baseline-sample", + "description": "A sample that aligned to WAF recommendations.", + "body": [ + "//", + "// Baseline deployment sample", + "//", + "", + "// Use this sample to deploy a Well-Architected aligned resource configuration.", + "", + "targetScope = 'resourceGroup'", + "", + "// ----------", + "// PARAMETERS", + "// ----------", + "", + "@description('The Azure location to deploy to.')", + "param location string = resourceGroup().location", + "", + "// ---------", + "// RESOURCES", + "// ---------", + "", + "@description('Baseline resource configuration')", + "module ${1} '../${2}}.bicep' = {", + " name: '${1}'", + " params: {", + " parLocation: location", + " parTags: {}", + " }", + "}" + ] + } +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 1c045cb9b..486fa341c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,6 +4,7 @@ "ms-azuretools.vscode-bicep", "vsls-contrib.codetour", "msazurermtools.azurerm-vscode-tools", - "bencoleman.armview" + "bencoleman.armview", + "bewhite.psrule-vscode" ] -} +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..d53406308 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "PSRule", + "problemMatcher": [ + "$PSRule" + ], + "label": "PSRule: Run analysis", + "presentation": { + "panel": "dedicated", + "clear": true + } + } + ] +} diff --git a/docs/wiki/Contributing.md b/docs/wiki/Contributing.md index 00daba785..5104a00a0 100644 --- a/docs/wiki/Contributing.md +++ b/docs/wiki/Contributing.md @@ -56,6 +56,7 @@ The following tooling/extensions are recommended to assist you developing for th - [CodeTour extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) - [ARM Tools extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=msazurermtools.azurerm-vscode-tools) - [ARM Template Viewer extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=bencoleman.armview) +- [PSRule extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=bewhite.psrule-vscode) - For visibility of Bracket Pairs: - Inside Visual Studio Code, add "editor.bracketPairColorization.enabled": true to your settings.json, to enable bracket pair colorization. diff --git a/infra-as-code/bicep/modules/hubNetworking/samples/baseline.sample.bicep b/infra-as-code/bicep/modules/hubNetworking/samples/baseline.sample.bicep new file mode 100644 index 000000000..0a7699067 --- /dev/null +++ b/infra-as-code/bicep/modules/hubNetworking/samples/baseline.sample.bicep @@ -0,0 +1,107 @@ +// +// Baseline deployment sample +// + +// Use this sample to deploy a Well-Architected aligned resource configuration. + +targetScope = 'resourceGroup' + +// ---------- +// PARAMETERS +// ---------- + +@description('The Azure location to deploy to.') +param location string = resourceGroup().location + +// --------- +// VARIABLES +// --------- + +// Company prefix for unit testing +var parCompanyPrefix = 'test' + +// --------- +// RESOURCES +// --------- + +@description('Baseline resource configuration') +module baseline_hub_network '../hubNetworking.bicep' = { + name: 'baseline_hub_network' + params: { + parLocation: location + parPublicIpSku: 'Standard' + parAzFirewallAvailabilityZones: [ + '1' + '2' + '3' + ] + parVpnGatewayConfig: {} + parExpressRouteGatewayConfig: {} + } +} + +@description('Baseline resource configuration using ExpressRoute') +module baseline_hub_network_with_ER '../hubNetworking.bicep' = { + name: 'baseline_hub_network_with_ER' + params: { + parLocation: location + parPublicIpSku: 'Standard' + parAzFirewallAvailabilityZones: [ + '1' + '2' + '3' + ] + parVpnGatewayConfig: {} + parExpressRouteGatewayConfig: { + name: '${parCompanyPrefix}-ExpressRoute-Gateway' + gatewaytype: 'ExpressRoute' + sku: 'ErGw1AZ' + vpntype: 'RouteBased' + vpnGatewayGeneration: 'None' + enableBgp: false + activeActive: false + enableBgpRouteTranslationForNat: false + enableDnsForwarding: false + asn: '65515' + bgpPeeringAddress: '' + bgpsettings: { + asn: '65515' + bgpPeeringAddress: '' + peerWeight: '5' + } + } + } +} + +@description('Baseline resource configuration using a VPN Gateway') +module baseline_hub_network_with_VPN '../hubNetworking.bicep' = { + name: 'baseline_hub_network_with_VPN' + params: { + parLocation: location + parPublicIpSku: 'Standard' + parAzFirewallAvailabilityZones: [ + '1' + '2' + '3' + ] + parVpnGatewayConfig: { + name: '${parCompanyPrefix}-Vpn-Gateway' + gatewaytype: 'Vpn' + sku: 'VpnGw1AZ' + vpntype: 'RouteBased' + generation: 'Generation1' + enableBgp: false + activeActive: false + enableBgpRouteTranslationForNat: false + enableDnsForwarding: false + asn: 65515 + bgpPeeringAddress: '' + bgpsettings: { + asn: 65515 + bgpPeeringAddress: '' + peerWeight: 5 + } + } + parExpressRouteGatewayConfig: {} + } +} diff --git a/infra-as-code/bicep/modules/hubNetworking/samples/minimum.sample.bicep b/infra-as-code/bicep/modules/hubNetworking/samples/minimum.sample.bicep new file mode 100644 index 000000000..dd5d84358 --- /dev/null +++ b/infra-as-code/bicep/modules/hubNetworking/samples/minimum.sample.bicep @@ -0,0 +1,26 @@ +// +// Minimum deployment sample +// + +// Use this sample to deploy the minimum resource configuration. + +targetScope = 'resourceGroup' + +// ---------- +// PARAMETERS +// ---------- + +@description('The Azure location to deploy to.') +param location string = resourceGroup().location + +// --------- +// RESOURCES +// --------- + +@description('Minimum resource configuration') +module minimum_hub_network '../hubNetworking.bicep' = { + name: 'minimum_hub_network' + params: { + parLocation: location + } +} diff --git a/infra-as-code/bicep/modules/publicIp/samples/baseline.sample.bicep b/infra-as-code/bicep/modules/publicIp/samples/baseline.sample.bicep new file mode 100644 index 000000000..1d26e65b5 --- /dev/null +++ b/infra-as-code/bicep/modules/publicIp/samples/baseline.sample.bicep @@ -0,0 +1,38 @@ +// +// Baseline deployment sample +// + +// Use this sample to deploy a Well-Architected aligned resource configuration. + +targetScope = 'resourceGroup' + +// ---------- +// PARAMETERS +// ---------- + +@description('The Azure location to deploy to.') +param location string = resourceGroup().location + +// --------- +// RESOURCES +// --------- + +@description('Baseline resource configuration') +module baseline_public_ip '../publicIp.bicep' = { + name: 'baseline_public_ip' + params: { + parPublicIpName: 'pip-baseline-ip' + parLocation: location + parPublicIpProperties: { } + parPublicIpSku: { + name: 'Standard' + tier: 'Regional' + } + parTags: {} + parAvailabilityZones: [ + '1' + '2' + '3' + ] + } +} diff --git a/infra-as-code/bicep/modules/publicIp/samples/minimum.sample.bicep b/infra-as-code/bicep/modules/publicIp/samples/minimum.sample.bicep new file mode 100644 index 000000000..306237090 --- /dev/null +++ b/infra-as-code/bicep/modules/publicIp/samples/minimum.sample.bicep @@ -0,0 +1,33 @@ +// +// Minimum deployment sample +// + +// Use this sample to deploy the minimum resource configuration. + +targetScope = 'resourceGroup' + +// ---------- +// PARAMETERS +// ---------- + +@description('The Azure location to deploy to.') +param location string = resourceGroup().location + +// --------- +// RESOURCES +// --------- + +@description('Minimum resource configuration') +module minimum_public_ip '../publicIp.bicep' = { + name: 'minimum_public_ip' + params: { + parPublicIpName: 'pip-minimum-ip' + parLocation: location + parPublicIpProperties: { } + parPublicIpSku: { + name: 'Basic' + tier: 'Regional' + } + parTags: {} + } +} diff --git a/ps-rule.yaml b/ps-rule.yaml new file mode 100644 index 000000000..c42e074be --- /dev/null +++ b/ps-rule.yaml @@ -0,0 +1,71 @@ +# +# PSRule for Azure configuration +# + +# Please see the documentation for all configuration options: +# https://aka.ms/ps-rule-azure +# https://aka.ms/ps-rule-azure/options +# https://aka.ms/ps-rule/options +# https://aka.ms/ps-rule-azure/bicep + +# Use rules from the following modules/ +include: + module: + - 'PSRule.Rules.Azure' + +# Require a minimum version of modules that include referenced baseline. +requires: + PSRule: '@pre >=2.3.2' + PSRule.Rules.Azure: '@pre >=1.18.1' + +# Reference the repository in output. +repository: + url: https://github.com/Azure/ALZ-Bicep + +execution: + # Ignore warnings for resources and objects that don't have any rules. + notProcessedWarning: false + +configuration: + # Enable expansion for Bicep source files. + AZURE_BICEP_FILE_EXPANSION: true + + # Expand Bicep module from Azure parameter files. + AZURE_PARAMETER_FILE_EXPANSION: true + + # Set timeout for expanding Bicep source files. + AZURE_BICEP_FILE_EXPANSION_TIMEOUT: 15 + +input: + pathIgnore: + # Ignore common files that don't need analysis. + - '**/bicepconfig.json' + - '*.md' + - '*.png' + - '.github/' + + # Exclude Bicep docs files + - docs/scripts/callModuleFromACR.example.bicep + + # Exclude Bicep module files + - 'infra-as-code/bicep/**/*.bicep' + + # Include samples/ test files from modules + - '!infra-as-code/bicep/**/samples/*.bicep' + +binding: + preferTargetInfo: true + targetType: + - resourceType + - type + +rule: + exclude: + # Ignore these recommendations for this repo. + - Azure.Resource.UseTags + - Azure.ACR.MinSku + - Azure.ACR.ContentTrust + - Azure.Policy.AssignmentAssignedBy + + # Currently a bug as of v1.15.2. Review in the next release. + - Azure.PublicIP.Name