azure-powershell icon indicating copy to clipboard operation
azure-powershell copied to clipboard

Inconsistent results between Search-AzGraph cmdlet and Azure Resource Graph Explorer from portal

Open gabrielvachon opened this issue 1 year ago • 7 comments

Description

I wrote a KQL query on the Azure Resource Graph Explorer and tried to get the same results with the Search-AzGraph command. However, on some queries I got less results (or none) when I queried from PowerShell.

Issue script & Debug output

PS> search-azGraph -Query @"
authorizationresources
| where type =~ 'microsoft.authorization/roleassignments'
| extend roleDefinitionId = tostring(properties.roleDefinitionId)
| join kind=inner authorizationresources on `$left.roleDefinitionId == `$right.id
| project id, name, roleDefinitionId, properties=properties1, roleName=tostring(properties1.roleName)
| where roleName=='Owner'
"@
**Gives 0 results, however i'm able to get data when executed on portal**

Environment data

PS> $psversionTable

Name                           Value
----                           -----
PSVersion                      7.4.1
PSEdition                      Core
GitCommitId                    7.4.1
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Module versions

PS> Get-Module Az*

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Script     2.15.0                Az.Accounts                         {Add-AzEnvironment, Clear-AzConfig, Clear-AzConte…
Script     0.13.0                Az.ResourceGraph                    {Search-AzGraph, Get-AzResourceGraphQuery, New-Az…

Error output

PS C:\Users\gvachon> Resolve-AzError

   HistoryId: 45

Message        : Operation returned an invalid status code 'BadRequest'
StackTrace     :    at Microsoft.Azure.Management.ResourceGraph.ResourceGraphClient.ResourcesWithHttpMessagesAsync(Quer
                 yRequest query, Dictionary`2 customHeaders, CancellationToken cancellationToken)
Exception      : Microsoft.Azure.Management.ResourceGraph.Models.ErrorResponseException
InvocationInfo : {Search-AzGraph}
Line           : $test = search-azGraph -Query @"

Position       : At line:1 char:9
                 + $test = search-azGraph -Query @"
                 +         ~~~~~~~~~~~~~~~~~~~~~~~~
HistoryId      : 45


   HistoryId: 37

Message        : Cannot bind argument to parameter 'ResourceGroupName' because it is an empty string.
StackTrace     :    at
                 System.Management.Automation.ParameterBinderBase.ValidateNullOrEmptyArgument(CommandParameterInternal
                 parameter, CompiledCommandParameter parameterMetadata, Type argumentType, Object parameterValue,
                 Boolean recurseIntoCollections)
                    at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal
                 parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
                    at
                 System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal
                 argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
                    at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32
                 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter,
                 ParameterBindingFlags flags)
                    at System.Management.Automation.ParameterBinderController.BindParameter(CommandParameterInternal
                 argument, ParameterBindingFlags flags)
                    at
                 System.Management.Automation.CmdletParameterBinderController.HandleUnboundMandatoryParameters(Int32
                 validParameterSetCount, Boolean processMissingMandatory, Boolean promptForMandatory, Boolean
                 isPipelineInputExpected, Collection`1& missingMandatoryParameters)
                    at
                 System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1
                 arguments)
                    at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
                    at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
                    at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary
                 psDefaultParameterValues)
                    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object
                 input)
                 --- End of stack trace from previous location ---
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object
                 input)
                    at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput,
                 CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][]
                 commandRedirections, FunctionContext funcContext)
                    at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
                    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame
                 frame)
Exception      : System.Management.Automation.ParameterBindingValidationException
InvocationInfo : {Get-AzResourceGraphQuery}
Line           : Get-AzResourceGraphQuery -Name "test-open-port22"
Position       : At line:1 char:1
                 + Get-AzResourceGraphQuery -Name "test-open-port22"
                 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HistoryId      : 37


   HistoryId: 31

Message        : Cannot validate argument on parameter 'Property'. The argument is null or empty. Provide an argument
                 that is not null or empty, and then try the command again.
StackTrace     :    at System.Management.Automation.ParameterBinderController.BindPositionalParametersInSet(UInt32
                 validParameterSets, Dictionary`2 nextPositionalParameters, CommandParameterInternal argument,
                 ParameterBindingFlags flags, ParameterBindingException& bindingException)
                    at System.Management.Automation.ParameterBinderController.BindPositionalParameters(Collection`1
                 unboundArguments, UInt32 validParameterSets, UInt32 defaultParameterSet, ParameterBindingException&
                 outgoingBindingException)
                    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidati
                 on(Collection`1 arguments)
                    at
                 System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1
                 arguments)
                    at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
                    at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
                    at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary
                 psDefaultParameterValues)
                    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object
                 input)
                 --- End of stack trace from previous location ---
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object
                 input)
                    at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput,
                 CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][]
                 commandRedirections, FunctionContext funcContext)
                    at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
                    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame
                 frame)
Exception      : System.Management.Automation.ParameterBindingValidationException
InvocationInfo : {Where-Object}
Line           : get-command | where $_.Name -contains "Az"
Position       : At line:1 char:21
                 + get-command | where $_.Name -contains "Az"
                 +                     ~~~~~~~
HistoryId      : 31

Message        : The argument is null or empty. Provide an argument that is not null or empty, and then try the
                 command again.
StackTrace     :    at System.Management.Automation.ValidateNotNullOrAttributeBase.Validate(Object arguments,
                 EngineIntrinsics engineIntrinsics)
                    at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal
                 parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
Exception      : System.Management.Automation.ValidationMetadataException
InvocationInfo : {Where-Object}
Line           : get-command | where $_.Name -contains "Az"
Position       : At line:1 char:21
                 + get-command | where $_.Name -contains "Az"
                 +                     ~~~~~~~
HistoryId      : 31


   HistoryId: 6

Message        : Missing an argument for parameter 'First'. Specify a parameter of type 'System.Int32' and try again.
StackTrace     :    at System.Management.Automation.ParameterBinderController.ReparseUnboundArguments()
                    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidati
                 on(Collection`1 arguments)
                    at
                 System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1
                 arguments)
                    at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
                    at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
                    at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary
                 psDefaultParameterValues)
                    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object
                 input)
                 --- End of stack trace from previous location ---
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object
                 input)
                    at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput,
                 CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][]
                 commandRedirections, FunctionContext funcContext)
                    at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
                    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame
                 frame)
Exception      : System.Management.Automation.ParameterBindingException
InvocationInfo : {Search-AzGraph}
Line           : search-azGraph -First -Query @"

Position       : At line:1 char:16
                 + search-azGraph -First -Query @"
                 +                ~~~~~~
HistoryId      : 6


   HistoryId: 2

Message        : Operation returned an invalid status code 'BadRequest'
StackTrace     :    at Microsoft.Azure.Management.ResourceGraph.ResourceGraphClient.ResourcesWithHttpMessagesAsync(Quer
                 yRequest query, Dictionary`2 customHeaders, CancellationToken cancellationToken)
Exception      : Microsoft.Azure.Management.ResourceGraph.Models.ErrorResponseException
InvocationInfo : {Search-AzGraph}
Line           : search-azGraph -Query @"

Position       : At line:1 char:1
                 + search-azGraph -Query @"
                 + ~~~~~~~~~~~~~~~~~~~~~~~~
HistoryId      : 2

gabrielvachon avatar Feb 29 '24 19:02 gabrielvachon

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @venu-l.

My guess: this may be caused by different API versions used by both products. But I'll leave the conclusion to Resource Graph team to make.

isra-fel avatar Mar 01 '24 06:03 isra-fel

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @venu-l.

My guess: this may be caused by different API versions used by both products. But I'll leave the conclusion to Resource Graph team to make.

Seems like they both use the same API.

When running Search-AzGraph -Query <query> -Debug , the URI points to https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2021-03-01. While the request I retrieved from the inspector shares the same URI.

Debug :

DEBUG: ============================ HTTP REQUEST ============================

HTTP Method:
POST

Absolute Uri:
https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2021-03-01

Headers:
Accept-Language               : en-US
x-ms-client-request-id        : f60ffc8d-ecae-49c9-acd1-c4255a18711f

Body:
{
  "subscriptions": [...],
  "query": "authorizationresources\n| where type =~ 'microsoft.authorization/roleassignments'\n| extend roleDefinitionId = tostring(properties.roleDefinitionId)\n| join kind=inner authorizationresources on $left.roleDefinitionId == $right.id\n| project id, name, roleDefinitionId, properties=properties1, roleName=tostring(properties1.roleName)\n| where roleName == 'Owner'",
  "options": {
    "$top": 100,
    "$skip": 0,
    "resultFormat": "objectArray",
    "allowPartialScopes": false
  }
}

gabrielvachon avatar Mar 01 '24 16:03 gabrielvachon

Can you share correlation ID + timestamp for a query run from PowerShell and for a query run from Portal so we can investigate on our side?

dhu5432 avatar Mar 20 '24 01:03 dhu5432

PowerShell :

  • Timestamp : Wed, 20 Mar 2024 15:21:57 GMT
  • Correlation ID : 7dc5182d-42cd-464b-a239-90343c0f0005

Portal :

  • Timestamp : Wed, 20 Mar 2024 15:28:17 GMT
  • Correlation ID : a6efbf34-f6a9-4643-95a0-5c578d6980fa

gabrielvachon avatar Mar 20 '24 15:03 gabrielvachon

I had to switch from using Search-AzGraph to a straight Invoke-RestMethod using the 2022-10-01 API version. otherwise, it was way out using the Search-AzGraph function which uses:

Absolute Uri: https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2021-03-01

Would be great if we could specify the API version.

machug avatar Aug 19 '24 03:08 machug