diff --git a/docs/CHANGELOG-v1.md b/docs/CHANGELOG-v1.md index 1835f568e5b..e9622e0d1e7 100644 --- a/docs/CHANGELOG-v1.md +++ b/docs/CHANGELOG-v1.md @@ -32,6 +32,10 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers ## Unreleased +- Updated rules: + - Template file + - Update `AZR-000212` to not fail with `languageVersion` 2.0 Templates + ## v1.33.0-B0088 (pre-release) What's changed since pre-release v1.33.0-B0053: diff --git a/src/PSRule.Rules.Azure/rules/Azure.Template.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Template.Rule.ps1 index c18977e3726..9948aaddc1d 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Template.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Template.Rule.ps1 @@ -11,7 +11,7 @@ Rule 'Azure.Template.TemplateFile' -Ref 'AZR-000212' -Type '.json' -If { (IsTemplateFile) } -Tag @{ release = 'GA'; ruleSet = '2020_06'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { $jsonObject = $PSRule.GetContentFirstOrDefault($TargetObject); $Assert.HasFields($jsonObject, @('$schema', 'contentVersion', 'resources')); - $jsonObject.PSObject.Properties | Within 'Name' '$schema', 'contentVersion', 'metadata', 'parameters', 'functions', 'variables', 'resources', 'outputs'; + $jsonObject.PSObject.Properties | Within 'Name' '$schema', 'languageVersion', 'contentVersion', 'definitions', 'metadata', 'parameters', 'functions', 'variables', 'resources', 'outputs'; } # Synopsis: Use a more recent version of the Azure template schema. diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.Template.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.Template.Tests.ps1 index 89dac6cf8e1..455c96390bc 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.Template.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.Template.Tests.ps1 @@ -48,7 +48,7 @@ Describe 'Azure.Template' -Tag 'Template' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 4; + $ruleResult.Length | Should -Be 5; ($ruleResult | Where-Object { $_.TargetName -like "*Resources.Template.json" }).TargetName | Should -BeLike "*Resources.Template.json"; ($ruleResult | Where-Object { $_.TargetName -like "*Resources.Template4.json" }).TargetName | Should -BeLike "*Resources.Template4.json"; } @@ -67,8 +67,8 @@ Describe 'Azure.Template' -Tag 'Template' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 4; - $ruleResult.TargetName.Replace('\', '/').Split('/')[-1] | Should -BeIn 'Resources.Template2.json', 'Resources.Template4.json', 'Resources.Template.Bicep1.json', 'Resources.Template.Bicep2.json'; + $ruleResult.Length | Should -Be 5; + $ruleResult.TargetName.Replace('\', '/').Split('/')[-1] | Should -BeIn 'Resources.Template2.json', 'Resources.Template4.json', 'Resources.Template.Bicep1.json', 'Resources.Template.Bicep2.json', 'Resources.Template.V2.json'; } It 'Azure.Template.TemplateScheme' { @@ -85,11 +85,12 @@ Describe 'Azure.Template' -Tag 'Template' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 5; + $ruleResult.Length | Should -Be 6; $ruleResult.TargetName.Replace('\', '/').Split('/')[-1] | Should -BeIn @( 'Resources.Template.Bicep1.json' 'Resources.Template.Bicep2.json' 'Resources.Template.json' + 'Resources.Template.V2.json' 'Resources.Template3.json' 'Resources.Template4.json' ); @@ -123,10 +124,11 @@ Describe 'Azure.Template' -Tag 'Template' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 4; + $ruleResult.Length | Should -Be 5; $ruleResult.TargetName.Replace('\', '/').Split('/')[-1] | Should -BeIn @( 'Resources.Template.Bicep1.json' 'Resources.Template.Bicep2.json' + 'Resources.Template.V2.json' 'Resources.Template3.json' 'Resources.Template4.json' ); @@ -688,7 +690,7 @@ Describe 'Azure.Template' -Tag 'Template' { $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' } | Sort-Object -Property { $_.TargetName.Replace('\', '/').Split('/')[-1] }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 3; - + $ruleResult.TargetName.Replace('\', '/').Split('/')[-1] | Should -BeIn @( 'Resources.Template2.json' 'Resources.Template3.json' diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.Template.V2.json b/tests/PSRule.Rules.Azure.Tests/Resources.Template.V2.json new file mode 100644 index 00000000000..82a7a1db9a5 --- /dev/null +++ b/tests/PSRule.Rules.Azure.Tests/Resources.Template.V2.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "10842470273706361200" + } + }, + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "The location resources will be deployed." + } + }, + "testNullable": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Nullable string parameter." + } + } + }, + "resources": { + "testResource": { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2023-01-01", + "name": "testStorageAccount", + "location": "[parameters('location')]", + "kind": "StorageV2", + "sku": { + "name": "Standard_LRS" + } + } + }, + "outputs": { + "testOutput": { + "type": "string", + "value": "[coalesce(parameters('testNullable'), 'Empty')]" + } + } +} \ No newline at end of file