Skip to content

Commit d6471e6

Browse files
authored
Fixes conditional secret as parameter or placeholder Azure#2054 (Azure#3095)
1 parent ddeb333 commit d6471e6

File tree

6 files changed

+181
-1
lines changed

6 files changed

+181
-1
lines changed

docs/CHANGELOG-v1.md

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ What's changed since pre-release v1.39.0:
3636
[#3062](https://github.com/Azure/PSRule.Rules.Azure/issues/3062)
3737
- Fixed `Azure.AppGw.AvailabilityZone` passes when a zonal configuration is used by @BernieWhite.
3838
[#3061](https://github.com/Azure/PSRule.Rules.Azure/issues/3061)
39+
- Fixed conditional secret as parameter or placeholder by @BernieWhite.
40+
[#2054](https://github.com/Azure/PSRule.Rules.Azure/issues/2054)
3941

4042
## v1.39.0
4143

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
// Test case for https://github.com/Azure/PSRule.Rules.Azure/issues/2054
5+
6+
param prefix string = 'super'
7+
param deployed bool = true
8+
9+
resource vault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
10+
name: 'vault1'
11+
}
12+
13+
module withSecret 'Tests.Bicep.1.child.bicep' = {
14+
name: 'withSecret'
15+
params: {
16+
name: '1'
17+
secret: deployed ? vault.getSecret('${prefix}secret1') : 'placeholder'
18+
}
19+
}
20+
21+
module withPlaceholder 'Tests.Bicep.1.child.bicep' = {
22+
name: 'withPlaceholder'
23+
params: {
24+
name: '2'
25+
secret: !deployed ? vault.getSecret('${prefix}secret1') : 'placeholder'
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
param name string
5+
6+
@secure()
7+
param secret string
8+
9+
resource secretToSet 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
10+
name: 'vault1/toSet${name}'
11+
properties: {
12+
value: secret
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3+
"contentVersion": "1.0.0.0",
4+
"metadata": {
5+
"_generator": {
6+
"name": "bicep",
7+
"version": "0.30.23.60470",
8+
"templateHash": "6760857410189558623"
9+
}
10+
},
11+
"parameters": {
12+
"prefix": {
13+
"type": "string",
14+
"defaultValue": "super"
15+
},
16+
"deployed": {
17+
"type": "bool",
18+
"defaultValue": true
19+
}
20+
},
21+
"resources": [
22+
{
23+
"type": "Microsoft.Resources/deployments",
24+
"apiVersion": "2022-09-01",
25+
"name": "withSecret",
26+
"properties": {
27+
"expressionEvaluationOptions": {
28+
"scope": "inner"
29+
},
30+
"mode": "Incremental",
31+
"parameters": {
32+
"name": {
33+
"value": "1"
34+
},
35+
"secret": "[if(parameters('deployed'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', 'vault1')), 'secretName', format('{0}secret1', parameters('prefix')))), createObject('value', 'placeholder'))]"
36+
},
37+
"template": {
38+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
39+
"contentVersion": "1.0.0.0",
40+
"metadata": {
41+
"_generator": {
42+
"name": "bicep",
43+
"version": "0.30.23.60470",
44+
"templateHash": "15661998235342522313"
45+
}
46+
},
47+
"parameters": {
48+
"name": {
49+
"type": "string"
50+
},
51+
"secret": {
52+
"type": "securestring"
53+
}
54+
},
55+
"resources": [
56+
{
57+
"type": "Microsoft.KeyVault/vaults/secrets",
58+
"apiVersion": "2022-07-01",
59+
"name": "[format('vault1/toSet{0}', parameters('name'))]",
60+
"properties": {
61+
"value": "[parameters('secret')]"
62+
}
63+
}
64+
]
65+
}
66+
}
67+
},
68+
{
69+
"type": "Microsoft.Resources/deployments",
70+
"apiVersion": "2022-09-01",
71+
"name": "withPlaceholder",
72+
"properties": {
73+
"expressionEvaluationOptions": {
74+
"scope": "inner"
75+
},
76+
"mode": "Incremental",
77+
"parameters": {
78+
"name": {
79+
"value": "2"
80+
},
81+
"secret": "[if(not(parameters('deployed')), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', 'vault1')), 'secretName', format('{0}secret1', parameters('prefix')))), createObject('value', 'placeholder'))]"
82+
},
83+
"template": {
84+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
85+
"contentVersion": "1.0.0.0",
86+
"metadata": {
87+
"_generator": {
88+
"name": "bicep",
89+
"version": "0.30.23.60470",
90+
"templateHash": "15661998235342522313"
91+
}
92+
},
93+
"parameters": {
94+
"name": {
95+
"type": "string"
96+
},
97+
"secret": {
98+
"type": "securestring"
99+
}
100+
},
101+
"resources": [
102+
{
103+
"type": "Microsoft.KeyVault/vaults/secrets",
104+
"apiVersion": "2022-07-01",
105+
"name": "[format('vault1/toSet{0}', parameters('name'))]",
106+
"properties": {
107+
"value": "[parameters('secret')]"
108+
}
109+
}
110+
]
111+
}
112+
}
113+
}
114+
]
115+
}

tests/PSRule.Rules.Azure.Tests/PSRule.Rules.Azure.Tests.csproj

+3
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@
290290
<None Update="Bicep\ExtensibilityTestCases\Tests.Bicep.1.json">
291291
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
292292
</None>
293+
<None Update="Bicep\SecretTestCases\Tests.Bicep.1.json">
294+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
295+
</None>
293296
</ItemGroup>
294297

295298
</Project>

tests/PSRule.Rules.Azure.Tests/TemplateVisitorTests.cs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ public void ProcessTemplate_WhenConditionalExistingReference_IgnoresExpand()
13091309
}
13101310

13111311
[Fact]
1312-
public void ProcessTemplate_WhenParented_ScopeIsExpected()
1312+
public void ProcessTemplate_WhenParented_ShouldReturnExpectedScope()
13131313
{
13141314
var resources = ProcessTemplate(GetSourcePath("sql.tests.json"), null, out _);
13151315

@@ -1366,6 +1366,25 @@ public void ProcessTemplate_WhenMicrosoftGraphType_ShouldIgnoreExtensibilityReso
13661366
Assert.Equal("ps-rule-test-deployment", actual["name"].Value<string>());
13671367
}
13681368

1369+
/// <summary>
1370+
/// Test case for https://github.com/Azure/PSRule.Rules.Azure/issues/2054
1371+
/// </summary>
1372+
[Fact]
1373+
public void ProcessTemplate_WhenConditionalSecretParameter_ShouldReturnSecretsPlaceholders()
1374+
{
1375+
var resources = ProcessTemplate(GetSourcePath("Bicep/SecretTestCases/Tests.Bicep.1.json"), null, out _);
1376+
1377+
Assert.NotNull(resources);
1378+
1379+
var actual = resources.Where(r => r["name"].Value<string>() == "vault1/toSet1").FirstOrDefault();
1380+
Assert.Equal("Microsoft.KeyVault/vaults/secrets", actual["type"].Value<string>());
1381+
Assert.Equal("{{SecretReference:supersecret1}}", actual["properties"]["value"].Value<string>());
1382+
1383+
actual = resources.Where(r => r["name"].Value<string>() == "vault1/toSet2").FirstOrDefault();
1384+
Assert.Equal("Microsoft.KeyVault/vaults/secrets", actual["type"].Value<string>());
1385+
Assert.Equal("placeholder", actual["properties"]["value"].Value<string>());
1386+
}
1387+
13691388
#region Helper methods
13701389

13711390
private static string GetSourcePath(string fileName)

0 commit comments

Comments
 (0)