Azure / Azure/bicep

Bicep snapshot inaccuracies and validation crashes with microsoftGraphV1

Open
#18,822 4 comments 0 reactions 0 assignees View on GitHub
Bicep Snapshot bug
Dominant language
Bicep
Stars
3.6k
Forks
830
Avg merge
1d 21m
Merged PRs (30d)
79

Description

**Bicep version**
Bicep CLI version 0.39.26 (1e90b06e40)

**Describe the bug**
Conditionally created objects generates `null`s instead of `[reference('...').appId]`

As a result bicep snapshot --mode validate fails:

command: `bicep snapshot bug-report.bicepparam --mode validate`

```
Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Text.Json.JsonElement.GetProperty(String)
at Bicep.Cli.Helpers.Snapshot.SnapshotDiffer.ConvertToWhatIfResource(JsonElement resource)
at System.Linq.Enumerable.SelectArrayIterator`2.Fill(ReadOnlySpan`1, Span`1, Func`2)
at System.Linq.Enumerable.SelectArrayIterator`2.ToList()
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1)
at Bicep.Cli.Helpers.Snapshot.SnapshotDiffer.CalculateChanges(Snapshot source, Snapshot target)
at Bicep.Cli.Commands.SnapshotCommand.RunAsync(SnapshotArguments args, CancellationToken cancellationToken)
at Bicep.Cli.Program.RunAsync(String[] args, CancellationToken cancellationToken)
at Bicep.Cli.Program.<>c__DisplayClass3_0.<b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Bicep.Cli.Program.RunWithCancellationAsync(Func`2 runFunc)
at Bicep.Cli.Program.Main(String[] args)
at Bicep.Cli.Program.(String[] args)
```

**To Reproduce**

bug-report.bicep:

```
extension microsoftGraphV1

param clientAppName string?
param clientAppName2 string = ''
param signInAudience string = 'AzureADMyOrg'
param appRoleId string = ''
param assignClientToResource bool = true

resource clientAppWorking 'Microsoft.Graph/applications@v1.0' = {
displayName: 'clientAppWorking'
uniqueName: 'clientAppWorking'
signInAudience: signInAudience
}

resource clientAppWorkingSp 'Microsoft.Graph/servicePrincipals@v1.0' = {
appId: clientAppWorking.appId
appRoleAssignmentRequired: true
}

resource clientApp 'Microsoft.Graph/applications@v1.0' = if (clientAppName != null) {
displayName: clientAppName!
uniqueName: clientAppName!
signInAudience: signInAudience
}

resource clientSp 'Microsoft.Graph/servicePrincipals@v1.0' = if (clientAppName != null) {
appId: clientApp.?appId!
appRoleAssignmentRequired: true
}

resource clientApp2 'Microsoft.Graph/applications@v1.0' = if (!empty(clientAppName2)) {
displayName: clientAppName2
uniqueName: clientAppName2
signInAudience: signInAudience
}

resource clientSp2 'Microsoft.Graph/servicePrincipals@v1.0' = if (!empty(clientAppName2)) {
appId: clientApp2.?appId!
appRoleAssignmentRequired: true
}

resource appRoleAssigment 'Microsoft.Graph/appRoleAssignedTo@v1.0' = if (clientAppName != null && assignClientToResource) {
appRoleId: appRoleId
principalId: clientSp.?id!
resourceId: '1a134043-d9f0-4e50-be25-12a81c6e6c7b'
}

output clientAppId string = clientApp.?appId ?? 'N/A'
output clientAppOid string = clientApp.?id ?? 'N/A'
output clientSpOid string = clientSp.?id ?? 'N/A'

```

bug-report.bicepparam

```
using './bug-report.bicep'

param clientAppName = 'asbasasaqiuhd'
param clientAppName2 = 'aasasaas'
```

Following snapshot is being generated:

```
{
"predictedResources": [
{
"properties": {
"displayName": "clientAppWorking",
"uniqueName": "clientAppWorking",
"signInAudience": "AzureADMyOrg"
},
"type": "Microsoft.Graph/applications@v1.0"
},
{
"properties": {
"appId": "[reference('clientAppWorking').appId]",
"appRoleAssignmentRequired": true
},
"type": "Microsoft.Graph/servicePrincipals@v1.0"
},
{
"properties": {
"displayName": "asbasasaqiuhd",
"uniqueName": "asbasasaqiuhd",
"signInAudience": "AzureADMyOrg"
},
"type": "Microsoft.Graph/applications@v1.0"
},
{
"properties": {
"appId": null,
"appRoleAssignmentRequired": true
},
"type": "Microsoft.Graph/servicePrincipals@v1.0"
},
{
"properties": {
"displayName": "aasasaas",
"uniqueName": "aasasaas",
"signInAudience": "AzureADMyOrg"
},
"type": "Microsoft.Graph/applications@v1.0"
},
{
"properties": {
"appId": null,
"appRoleAssignmentRequired": true
},
"type": "Microsoft.Graph/servicePrincipals@v1.0"
},
{
"properties": {
"appRoleId": "",
"principalId": null,
"resourceId": "1a134043-d9f0-4e50-be25-12a81c6e6c7b"
},
"type": "Microsoft.Graph/appRoleAssignedTo@v1.0"
}
],
"diagnostics": []
}
```

Notice how `appId` and `principalId`are being set to null on resources using conditionally created resources

**Additional context**

This is extracted from bigger template

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with bug-report.bicep and bug-report.bicepparam, then start at SnapshotCommand.RunAsync and SnapshotDiffer.ConvertToWhatIfResource in the stack trace. Trace how conditional resource references become null in the generated predictedResources and how validation expects those entries. Done means the snapshot preserves the expected reference expressions and bicep snapshot --mode validate completes without the KeyNotFoundException.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure
Domain
cli, compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.