Skip to content

[BUG] Bicep expansion fails when AVM Web Site managedIdentities.userAssignedResourceIds contains a module output #3881

Description

Existing rule

No response

Description of the issue

Bicep expansion fails when AVM Web Site managedIdentities.userAssignedResourceIds contains a module output

Description

PSRule for Azure fails during Bicep parameter file expansion when a resource ID returned from another Bicep module is passed to the managedIdentities.userAssignedResourceIds parameter of the Azure Verified Module:

br/public:avm/res/web/site:0.24.0

The Bicep itself is valid and the resource ID is provided through the normal Bicep module output mechanism.

The failure has been isolated specifically to the managedIdentities parameter. Removing managedIdentities allows PSRule expansion to complete.

The error returned by PSRule is:

Invoke-PSRule: Failed to expand bicep source '<path>\main.canary.bicepparam'. Exception calling "GetBicepParamResources" with "2" argument(s): "Cannot process argument because the value of argument "name" is not valid. Change the value of the "name" argument and run the operation again."

Environment

Please let me know if additional environment information is required.

PSRule version:                 2.9.0
PSRule.Rules.Azure version:     1.47.0
PowerShell version:             7.6.4
Bicep CLI version:              0.42.1 (caea9302e8)
OS:                             Windows
AVM module:                     avm/res/web/site:0.24.0
Input type:                     .bicepparam

PSRule configuration

Bicep/Bicepparam expansion is enabled.

Relevant configuration is approximately:

configuration:
  AZURE_BICEP_FILE_EXPANSION: true
  AZURE_BICEP_PARAMS_FILE_EXPANSION: true

Other unrelated configuration has been omitted.

Scenario

A user-assigned managed identity is created using a Bicep/AVM module.

The module exposes the identity resource ID as an output.

That output is then passed to the AVM Web Site module:

module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.6.0' = {
  name: 'userAssignedIdentity'
  scope: resourceGroup
  params: {
    // ...
  }
}

module appService 'br/public:avm/res/web/site:0.24.0' = {
  scope: resourceGroup
  name: 'appService'
  params: {
    kind: 'app,linux'
    name: appServiceName
    serverFarmResourceId: appServicePlan.outputs.resourceId
    location: location

    managedIdentities: {
      userAssignedResourceIds: [
        userAssignedIdentity.outputs.resourceId
      ]
    }

    // ...
  }
}

The important part of the reproduction is:

managedIdentities: {
  userAssignedResourceIds: [
    userAssignedIdentity.outputs.resourceId
  ]
}

Actual behavior

When PSRule expands the .bicepparam file, expansion fails with:

Exception calling "GetBicepParamResources" with "2" argument(s):
"Cannot process argument because the value of argument "name" is not valid.
Change the value of the "name" argument and run the operation again."

Unlike some other Bicep expansion failures, the error does not identify:

  • the deployment/resource that failed;
  • the symbolic resource name;
  • the ARM expression being evaluated;
  • the JSON path; or
  • the Bicep/ARM source location.

This makes the source of the failure difficult to identify.

Expected behavior

PSRule should successfully expand the deployment when a valid resource ID from a module output is passed as an AVM module parameter.

In particular, passing:

userAssignedIdentity.outputs.resourceId

as an item in:

managedIdentities.userAssignedResourceIds

should be supported when the module output resolves to a valid user-assigned managed identity resource ID.

This pattern works as a normal Bicep/ARM deployment dependency.

Isolation performed

The issue was isolated by progressively removing modules and parameters.

1. Removing the App Service module

Removing:

module appService 'br/public:avm/res/web/site:0.24.0'

allows PSRule expansion to proceed.

2. Reducing the App Service module

The App Service module was reduced to a minimal configuration and its parameters were added back individually.

The failure was isolated specifically to:

managedIdentities: {
  userAssignedResourceIds: [
    userAssignedIdentity.outputs.resourceId
  ]
}

Removing only managedIdentities allows expansion to succeed.

Adding it again causes:

Cannot process argument because the value of argument "name" is not valid.

3. Other AVM parameters tested

Other App Service parameters were individually tested, including configuration related to:

  • site configuration;
  • VNet integration;
  • private endpoints;
  • diagnostic settings;
  • App Service configuration/app settings;
  • Key Vault access identity.

These were not responsible for this particular error.

The error follows the managedIdentities parameter.

4. PowerShell version

The PowerShell version is newer than the versions associated with the previously documented PowerShell 7.4.0/7.4.1 "name" is not valid issue.

Therefore this does not appear to be that PowerShell version issue.

Suspected cause

This appears to be related to PSRule expansion of a module output when that output is subsequently used by the AVM Web Site module to construct the ARM userAssignedIdentities object.

The ARM representation of a user-assigned identity uses the resource ID as an object property name, conceptually:

{
  "identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/.../resourceGroups/.../providers/Microsoft.ManagedIdentity/userAssignedIdentities/example": {}
    }
  }
}

The AVM input is an array of resource IDs:

managedIdentities: {
  userAssignedResourceIds: [
    userAssignedIdentity.outputs.resourceId
  ]
}

The AVM module subsequently transforms those resource IDs into the keys of the userAssignedIdentities object.

My suspicion is therefore that PSRule's expansion engine is attempting to construct an object/property name before the module output has been materialized to a concrete string.

This would also be consistent with the exception referring specifically to an invalid "name" rather than reporting an invalid managed identity resource ID.

Why this may be a PSRule expansion issue

The Bicep dependency itself is valid:

userAssignedIdentity.outputs.resourceId

Using an output from one module as an input to another module is a standard Bicep pattern and also establishes the appropriate deployment dependency.

The issue appears only while PSRule is statically expanding the deployment.

It therefore appears that PSRule's ARM expansion/evaluation may not be preserving or resolving the module output correctly when the resulting value is used as an object property name.

Minimal conceptual reproduction

The issue can be summarized as:

module identity './identity.bicep' = {
  name: 'identity'
  params: {
    // ...
  }
}

module site 'br/public:avm/res/web/site:0.24.0' = {
  name: 'site'
  params: {
    name: 'example-app'
    location: location
    serverFarmResourceId: serverFarmResourceId

    managedIdentities: {
      userAssignedResourceIds: [
        identity.outputs.resourceId
      ]
    }
  }
}

Where identity.bicep exposes:

output resourceId string = identity.id

PSRule expansion fails when processing the Web Site module.

Workaround

A possible workaround is to provide PSRule with a resource ID that can be calculated statically instead of consuming the module output, for example by constructing the managed identity resource ID independently and adding an explicit dependency on the identity module.

However, this is undesirable because:

  1. The identity resource ID is already exposed by the module.
  2. Using the module output is the natural Bicep dependency pattern.
  3. Reconstructing the resource ID duplicates information already known by the identity module.
  4. An explicit dependsOn may then be required because the implicit dependency established by the module output has been removed.
  5. The workaround changes otherwise valid Bicep specifically to accommodate static analysis.

An existing resource declaration can similarly be used to obtain the identity .id, but this also introduces a redundant declaration of a resource that is already created by another module in the same deployment.

Additional observations

During investigation I encountered other PSRule expansion limitations involving AVM modules where values normally resolved by ARM at deployment time needed to be made explicit for PSRule.

For example:

  • A Key Vault secret nested deployment required a placeholder for an unresolved value parameter via AZURE_PARAMETER_DEFAULTS.
  • Private endpoint location needed to be supplied explicitly rather than allowing the AVM module to derive it from the subnet resource.

Those issues could be worked around by providing PSRule with static values.

The managedIdentities case is different because the value already comes from a valid Bicep module output and should naturally be resolvable through the deployment dependency graph.

Questions

  1. Is the use of a module output as an element of managedIdentities.userAssignedResourceIds expected to be supported during Bicep expansion?
  2. Is there a known limitation when a module output ultimately becomes an ARM object property name/key?
  3. Is the "value of argument 'name' is not valid" exception coming from PSRule's handling of the generated userAssignedIdentities object?
  4. Is there a recommended PSRule configuration/workaround that preserves the normal Bicep module-output dependency rather than requiring the resource ID to be reconstructed?
  5. Could the expansion error be enhanced to report the nested deployment, ARM expression, and JSON path that caused this exception?

Error messages

No response

Reproduction

See the issue report for reproduction steps

Version of PSRule

2.9.0

Version of PSRule for Azure

1.47.0

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfeature: pre-flight-expansionIssues relating to expansion of ARM and Bicep.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions