public async Task <List <Resource> > QueryAsync(string query, List <string> targetSubscriptions)
        {
            Guard.NotNullOrWhitespace(query, nameof(query));

            var graphClient = await GetOrCreateClient();

            try
            {
                var queryRequest = new QueryRequest(targetSubscriptions, query);
                var response     = await graphClient.ResourcesAsync(queryRequest);

                var foundResources = ParseQueryResults(response);

                return(foundResources);
            }
            catch (ErrorResponseException responseException)
            {
                if (responseException.Response != null)
                {
                    if (responseException.Response.StatusCode == HttpStatusCode.Forbidden)
                    {
                        var unauthorizedException = new UnauthorizedException(QueryApplicationId, targetSubscriptions);
                        _logger.LogCritical(unauthorizedException, "Unable to query Azure Resource Graph");
                        throw unauthorizedException;
                    }

                    if (responseException.Response.StatusCode == HttpStatusCode.BadRequest)
                    {
                        var response     = JToken.Parse(responseException.Response.Content);
                        var errorDetails = response["error"]?["details"];
                        if (errorDetails != null)
                        {
                            var errorCodes = new List <string>();
                            foreach (var detailEntry in errorDetails)
                            {
                                errorCodes.Add(detailEntry["code"]?.ToString());
                            }

                            if (errorCodes.Any(errorCode => errorCode.Equals("NoValidSubscriptionsInQueryRequest", StringComparison.InvariantCultureIgnoreCase)))
                            {
                                var invalidSubscriptionException = new QueryContainsInvalidSubscriptionException(targetSubscriptions);
                                _logger.LogCritical(invalidSubscriptionException, "Unable to query Azure Resource Graph");
                                throw invalidSubscriptionException;
                            }
                        }
                    }
                }

                throw;
            }
        }
Exemple #2
0
        private async Task <TResponse> InteractWithAzureResourceGraphAsync <TResponse>(string queryName, string query, List <string> targetSubscriptions, Func <ResourceGraphClient, Task <TResponse> > interactionFunc)
        {
            Guard.NotNullOrWhitespace(query, nameof(query));

            var retryPolicy = Policy.Handle <ErrorResponseException>(ex => ex.Response?.StatusCode == HttpStatusCode.Unauthorized)
                              .RetryAsync(retryCount: 3, OnRetryAsync);

            return(await retryPolicy.ExecuteAsync(async() =>
            {
                var graphClient = await GetOrCreateClient();

                bool isSuccessfulDependency = false;
                using (var dependencyMeasurement = DependencyMeasurement.Start())
                {
                    try
                    {
                        var response = await interactionFunc(graphClient);
                        isSuccessfulDependency = true;

                        return response;
                    }
                    catch (ErrorResponseException responseException)
                    {
                        if (responseException.Response != null)
                        {
                            if (responseException.Response.StatusCode == HttpStatusCode.Forbidden)
                            {
                                var unauthorizedException = CreateUnauthorizedException(targetSubscriptions);

                                throw unauthorizedException;
                            }

                            if (responseException.Response.StatusCode == HttpStatusCode.BadRequest)
                            {
                                var response = JToken.Parse(responseException.Response.Content);
                                var errorDetails = response["error"]?["details"];
                                if (errorDetails != null)
                                {
                                    var errorCodes = new List <string>();
                                    foreach (var detailEntry in errorDetails)
                                    {
                                        errorCodes.Add(detailEntry["code"]?.ToString());
                                    }

                                    if (errorCodes.Any(errorCode => errorCode.Equals("NoValidSubscriptionsInQueryRequest", StringComparison.InvariantCultureIgnoreCase)))
                                    {
                                        var invalidSubscriptionException = new QueryContainsInvalidSubscriptionException(targetSubscriptions);
                                        _logger.LogCritical(invalidSubscriptionException, "Unable to query Azure Resource Graph");
                                        throw invalidSubscriptionException;
                                    }
                                }
                            }
                        }

                        throw;
                    }
                    finally
                    {
                        var contextualInformation = new Dictionary <string, object>
                        {
                            { "Query", query },
                            { "QueryName", queryName },
                            { "Subscriptions", targetSubscriptions }
                        };

                        _logger.LogDependency("Azure Resource Graph", query, "Query", isSuccessfulDependency, dependencyMeasurement, contextualInformation);
                    }
                }
            }));
        }
        public async Task<JObject> QueryAsync(string query)
        {
            Guard.NotNullOrWhitespace(query, nameof(query));

            var graphClient = await GetOrCreateClient();

            bool isSuccessfulDependency = false;
            using (var dependencyMeasurement = DependencyMeasurement.Start())
            {
                try
                {
                    var queryRequest = new QueryRequest(Subscriptions, query);
                    var response = await graphClient.ResourcesAsync(queryRequest);
                    isSuccessfulDependency = true;
                    return response.Data as JObject;
                }
                catch (ErrorResponseException responseException)
                {
                    if (responseException.Response != null)
                    {
                        if (responseException.Response.StatusCode == HttpStatusCode.Forbidden)
                        {
                            var unauthorizedException = new UnauthorizedException(QueryApplicationId, Subscriptions);
                            _logger.LogCritical(unauthorizedException, "Unable to query Azure Resource Graph");
                            throw unauthorizedException;
                        }

                        if (responseException.Response.StatusCode == HttpStatusCode.BadRequest)
                        {
                            var response = JToken.Parse(responseException.Response.Content);
                            var errorDetails = response["error"]?["details"];
                            if (errorDetails != null)
                            {
                                var errorCodes = new List<string>();
                                foreach (var detailEntry in errorDetails)
                                {
                                    errorCodes.Add(detailEntry["code"]?.ToString());
                                }

                                if (errorCodes.Any(errorCode => errorCode.Equals("NoValidSubscriptionsInQueryRequest", StringComparison.InvariantCultureIgnoreCase)))
                                {
                                    var invalidSubscriptionException = new QueryContainsInvalidSubscriptionException(Subscriptions);
                                    _logger.LogCritical(invalidSubscriptionException, "Unable to query Azure Resource Graph");
                                    throw invalidSubscriptionException;
                                }
                            }
                        }
                    }

                    throw;
                }
                finally
                {
                    var contextualInformation = new Dictionary<string, object>
                    {
                        {"Query", query},
                        {"Subscriptions", Subscriptions}
                    };

                    _logger.LogDependency("Azure Resource Graph", query, "Query", isSuccessfulDependency, dependencyMeasurement, contextualInformation);
                }
            }
        }