Skip to content

Commit 194b235

Browse files
authored
Fixed GetBicepParamResources exception when expanding Microsoft Graph Azure#3062 (Azure#3093)
1 parent 25a6389 commit 194b235

File tree

8 files changed

+181
-1
lines changed

8 files changed

+181
-1
lines changed

docs/CHANGELOG-v1.md

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers
2929

3030
## Unreleased
3131

32+
What's changed since pre-release v1.39.0:
33+
34+
- Bug fixes:
35+
- Fixed `GetBicepParamResources` exception when expanding `Microsoft.Graph/groups` resource by @BernieWhite.
36+
[#3062](https://github.com/Azure/PSRule.Rules.Azure/issues/3062)
37+
3238
## v1.39.0
3339

3440
What's changed since pre-release v1.38.0:

src/PSRule.Rules.Azure/Common/JsonExtensions.cs

+17
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ internal static class JsonExtensions
1919
private const string PROPERTY_TYPE = "type";
2020
private const string PROPERTY_FIELD = "field";
2121
private const string PROPERTY_EXISTING = "existing";
22+
private const string PROPERTY_IMPORT = "import";
2223
private const string PROPERTY_SCOPE = "scope";
2324
private const string PROPERTY_SUBSCRIPTION_ID = "subscriptionId";
2425
private const string PROPERTY_RESOURCE_GROUP = "resourceGroup";
@@ -508,11 +509,27 @@ internal static bool IsEmpty(this JToken value)
508509
(value.Type == JTokenType.String && string.IsNullOrEmpty(value.Value<string>()));
509510
}
510511

512+
/// <summary>
513+
/// Resources with the <c>existing</c> property set to <c>true</c> are references to existing resources.
514+
/// </summary>
515+
/// <param name="o">The resource <seealso cref="JObject"/>.</param>
516+
/// <returns>Returns <c>true</c> if the resource is a reference to an existing resource.</returns>
511517
internal static bool IsExisting(this JObject o)
512518
{
513519
return o != null && o.TryBoolProperty(PROPERTY_EXISTING, out var existing) && existing != null && existing.Value;
514520
}
515521

522+
/// <summary>
523+
/// Resources with an <c>import</c> property set to a non-empty string refer to extensibility provided resources.
524+
/// For example, Microsoft Graph.
525+
/// </summary>
526+
/// <param name="o">The resource <seealso cref="JObject"/>.</param>
527+
/// <returns>Returns <c>true</c> if the resource is imported from an extensibility provider.</returns>
528+
internal static bool IsImport(this JObject o)
529+
{
530+
return o != null && o.TryStringProperty(PROPERTY_IMPORT, out var s) && !string.IsNullOrEmpty(s);
531+
}
532+
516533
internal static bool TryResourceType(this JObject o, out string type)
517534
{
518535
type = default;

src/PSRule.Rules.Azure/Data/Template/TemplateVisitor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1231,7 +1231,7 @@ private void Resources(TemplateContext context, JObject resources)
12311231
{
12321232
Reference(context, p.Name, resource);
12331233
}
1234-
else
1234+
else if (!resource.IsImport())
12351235
{
12361236
r.AddRange(ResourceExpand(context, p.Name, resource));
12371237
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
// Test case for https://github.com/Azure/PSRule.Rules.Azure/issues/3062
5+
6+
extension microsoftGraphV1_0
7+
8+
var appRoleId = 'appRoleId'
9+
var certKey = 'certKey'
10+
11+
resource resourceApp 'Microsoft.Graph/[email protected]' = {
12+
uniqueName: 'ExampleResourceApp'
13+
displayName: 'Example Resource Application'
14+
appRoles: [
15+
{
16+
id: appRoleId
17+
allowedMemberTypes: ['User', 'Application']
18+
description: 'Read access to resource app data'
19+
displayName: 'ResourceAppData.Read.All'
20+
value: 'ResourceAppData.Read.All'
21+
isEnabled: true
22+
}
23+
]
24+
}
25+
26+
resource resourceSp 'Microsoft.Graph/[email protected]' = {
27+
appId: resourceApp.appId
28+
}
29+
30+
resource clientApp 'Microsoft.Graph/[email protected]' = {
31+
uniqueName: 'ExampleClientApp'
32+
displayName: 'Example Client Application'
33+
keyCredentials: [
34+
{
35+
displayName: 'Example Client App Key Credential'
36+
usage: 'Verify'
37+
type: 'AsymmetricX509Cert'
38+
key: certKey
39+
}
40+
]
41+
}
42+
43+
resource clientSp 'Microsoft.Graph/[email protected]' = {
44+
appId: clientApp.appId
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3+
"languageVersion": "2.1-experimental",
4+
"contentVersion": "1.0.0.0",
5+
"metadata": {
6+
"_EXPERIMENTAL_WARNING": "This template uses ARM features that are experimental. Experimental features should be enabled for testing purposes only, as there are no guarantees about the quality or stability of these features. Do not enable these settings for any production usage, or your production environment may be subject to breaking.",
7+
"_EXPERIMENTAL_FEATURES_ENABLED": [
8+
"Extensibility"
9+
],
10+
"_generator": {
11+
"name": "bicep",
12+
"version": "0.30.23.60470",
13+
"templateHash": "2001503425732761903"
14+
}
15+
},
16+
"variables": {
17+
"appRoleId": "appRoleId",
18+
"certKey": "certKey"
19+
},
20+
"imports": {
21+
"MicrosoftGraph": {
22+
"provider": "MicrosoftGraph",
23+
"version": "0.1.8-preview"
24+
}
25+
},
26+
"resources": {
27+
"resourceApp": {
28+
"import": "MicrosoftGraph",
29+
"type": "Microsoft.Graph/[email protected]",
30+
"properties": {
31+
"uniqueName": "ExampleResourceApp",
32+
"displayName": "Example Resource Application",
33+
"appRoles": [
34+
{
35+
"id": "[variables('appRoleId')]",
36+
"allowedMemberTypes": [
37+
"User",
38+
"Application"
39+
],
40+
"description": "Read access to resource app data",
41+
"displayName": "ResourceAppData.Read.All",
42+
"value": "ResourceAppData.Read.All",
43+
"isEnabled": true
44+
}
45+
]
46+
}
47+
},
48+
"resourceSp": {
49+
"import": "MicrosoftGraph",
50+
"type": "Microsoft.Graph/[email protected]",
51+
"properties": {
52+
"appId": "[reference('resourceApp').appId]"
53+
},
54+
"dependsOn": [
55+
"resourceApp"
56+
]
57+
},
58+
"clientApp": {
59+
"import": "MicrosoftGraph",
60+
"type": "Microsoft.Graph/[email protected]",
61+
"properties": {
62+
"uniqueName": "ExampleClientApp",
63+
"displayName": "Example Client Application",
64+
"keyCredentials": [
65+
{
66+
"displayName": "Example Client App Key Credential",
67+
"usage": "Verify",
68+
"type": "AsymmetricX509Cert",
69+
"key": "[variables('certKey')]"
70+
}
71+
]
72+
}
73+
},
74+
"clientSp": {
75+
"import": "MicrosoftGraph",
76+
"type": "Microsoft.Graph/[email protected]",
77+
"properties": {
78+
"appId": "[reference('clientApp').appId]"
79+
},
80+
"dependsOn": [
81+
"clientApp"
82+
]
83+
}
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"experimentalFeaturesEnabled": {
3+
"optionalModuleNames": true,
4+
"extensibility": true
5+
},
6+
"extensions": {
7+
"microsoftGraphV1_0": "br:mcr.microsoft.com/bicep/extensions/microsoftgraph/v1.0:0.1.8-preview"
8+
}
9+
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@
287287
<None Update="Template.Policy.WithDeployment.json">
288288
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
289289
</None>
290+
<None Update="Bicep\ExtensibilityTestCases\Tests.Bicep.1.json">
291+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
292+
</None>
290293
</ItemGroup>
291294

292295
</Project>

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

+15
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,21 @@ public void ProcessTemplate_WhenParented_ScopeIsExpected()
13511351
Assert.Equal("/subscriptions/ffffffff-ffff-ffff-ffff-ffffffffffff/resourceGroups/ps-rule-test-rg/providers/Microsoft.Sql/servers/server01/databases/db02", actual["scope"].Value<string>());
13521352
}
13531353

1354+
/// <summary>
1355+
/// Test case for https://github.com/Azure/PSRule.Rules.Azure/issues/3062
1356+
/// </summary>
1357+
[Fact]
1358+
public void ProcessTemplate_WhenMicrosoftGraphType_ShouldIgnoreExtensibilityResources()
1359+
{
1360+
var resources = ProcessTemplate(GetSourcePath("Bicep/ExtensibilityTestCases/Tests.Bicep.1.json"), null, out _);
1361+
1362+
Assert.Single(resources);
1363+
1364+
var actual = resources[0];
1365+
Assert.Equal("Microsoft.Resources/deployments", actual["type"].Value<string>());
1366+
Assert.Equal("ps-rule-test-deployment", actual["name"].Value<string>());
1367+
}
1368+
13541369
#region Helper methods
13551370

13561371
private static string GetSourcePath(string fileName)

0 commit comments

Comments
 (0)