Azure / azure-powershell

Microsoft Azure PowerShell
Other
4.27k stars 3.87k forks source link

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

Open gabrielvachon opened 9 months ago

gabrielvachon commented 9 months ago

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
microsoft-github-policy-service[bot] commented 9 months ago

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

isra-fel commented 9 months ago

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.

microsoft-github-policy-service[bot] commented 9 months ago

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

gabrielvachon commented 9 months ago

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
  }
}
dhu5432 commented 8 months ago

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?

gabrielvachon commented 8 months ago

PowerShell :

Portal :

machug commented 3 months ago

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.