Connecting to the Resource Graph Client via the Resource Graph SDK
In order to retrieve information from Azure Subscriptions someone at a client wanted to use the Resource Graph API. For this they were building an ASP.Net Core application and where using the C# SDK. The problem that they were having was related to the authentication.
Azure Resource Graph
The resource graph is a service in Azure that is designed to extend Azure Resource Management by providing efficient and performant resource exploration with the ability to query at scale across a given set of subscriptions so that you can effectively govern your environment.
For this you make use of kusto queries that you send to the API.
More information about the Azure Resource Graph: https://docs.microsoft.com/en-us/azure/governance/resource-graph/overview
Implementation
To connect to the Resource Graph an authentication object needs to exist. We wanted to use a service principal. The process using this code is a background job and did not have any user interaction.
To use the Resource Graph within a C# application add the following NuGet packages:
- Microsoft.Azure.Management.ResourceGraph: SDK for C# applications.
- Microsoft.Azure.Services.AppAuthentication: Package for handling the authentication.
The resource graph NuGet package contains the “ResourceGraphClient” that is needed to perform queries against the resource graph API.
To be able to initiate a “ResourceGraphClient” it requires an object called “ServiceClientCredentials”. The "ServiceClientCredentials" object is a base class for the "TokenCredentials" object that we can construct for the service principal.
Note: The demo code is a simple setup. When using this in production you should save secure value in a vault and configuration values in a config file.
First off, we create a helper class with a method that will retrieve the "ServiceClientCredentials" object.
using Microsoft.IdentityModel.Clients.ActiveDirectory; using Microsoft.Rest; using System.Threading.Tasks; namespace GraphClient { public static class AuthenticationHelper { public static async Task<ServiceClientCredentials> GetServiceClientCredentials(string resource, string clientId, string clientSecret, string authority) { AuthenticationContext authContext = new AuthenticationContext(authority); AuthenticationResult authResult = await authContext.AcquireTokenAsync(resource, new ClientCredential(clientId, clientSecret)); string accessToken = authResult.AccessToken; ServiceClientCredentials serviceClientCreds = new TokenCredentials(authResult.AccessToken); return serviceClientCreds; } } }
The class contains a method to retrieve the required object. This is done by specifying the authentication context (the Azure AD tenant) and retrieving a token by specifying the resource "https://management.core.windows.net" (default for the resource graph API), the client id and client secret. With the token we can initiate the "TokenCredentials" object that derives from the "ServiceClientCredentials" class.
With this class and method in place we will develop the other peace needed to perform the queries.
using Microsoft.Azure.Management.ResourceGraph; using Microsoft.Azure.Management.ResourceGraph.Models; using System; using System.Collections.Generic; namespace GraphClient { class Program { static void Main(string[] args) { string clientId = "[clientid]"; string clientSecret = "[clientSecret]"; string tenantId = "[tenantId]"; string subscriptionId = "[subscriptionId]"; string query = "Resources | project name, type | limit 5"; string authority = $"https://login.microsoftonline.com/{tenantId}"; ResourceGraphClient client = new ResourceGraphClient(AuthenticationHelper.GetServiceClientCredentials("https://management.core.windows.net", clientId, clientSecret, authority).Result); var response = client.Resources(new QueryRequest(new List<string>(){ subscriptionId }, query)); Console.WriteLine(response); } } }
This part of the code initiates the "ResourceClient" class that will execute a Kusto query via the "Resources" mehod.