I am trying to run the compliance score by resource type query using Resource Graph SDK .net. These are the nuget packages I have added.
<PackageReference Include="Azure.ResourceManager" Version="1.13.2" />
<PackageReference Include="Azure.ResourceManager.Purview" Version="1.1.0" />
<PackageReference Include="Azure.ResourceManager.ResourceGraph" Version="1.0.1" />
I have created a service class and then calling that method in my controller to get the API response. Here is the service class
public class ComplianceService
{
private readonly ArmClient _armClient;
public ComplianceService(string tenantId, string clientId, string clientSecret)
{
var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
_armClient = new ArmClient(credential);
}
public async Task<QueryResponse> GetComplianceScoreAsync()
{
var subscriptionIds = new List<string>();
await foreach (var sub in _armClient.GetSubscriptions().GetAllAsync())
{
subscriptionIds.Add(sub.Data.SubscriptionId);
}
if (subscriptionIds.Count == 0)
{
throw new Exception("No subscriptions found.");
}
var query = @"My query";
var request = new ResourceQueryContent(query)
{
Subscriptions = { subscriptionIds.ToString() }
};
.................
return response;
}
}
Now I am stuck on the part where I don't know how to call the query and get the response. Also, I want to get all the subscriptions dynamically. I am using .Net core 8+ I am new to running Azure SDK's and running resource graph queries. What can I try next?
there are some issues with your code, here is the updated code
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.ResourceGraph;
using Azure.ResourceManager.ResourceGraph.Models;
using Azure.ResourceManager.Resources;
public class ComplianceService
{
private readonly ArmClient _armClient;
public ComplianceService(string tenantId, string clientId, string clientSecret)
{
var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
_armClient = new ArmClient(credential);
}
public async Task<ResourceQueryResult> GetComplianceScoreAsync()
{
// Get the tenant resource - this is the key to accessing subscriptions and running queries
var tenant = _armClient.GetTenants().GetAllAsync().GetAsyncEnumerator().Current;
// Get all subscriptions dynamically
var subscriptionIds = new List<string>();
await foreach (var subscription in tenant.GetSubscriptions().GetAllAsync())
{
subscriptionIds.Add(subscription.Data.SubscriptionId);
}
if (subscriptionIds.Count == 0)
{
throw new Exception("No subscriptions found.");
}
// Your compliance score query
var query = @"
PolicyResources
| where type =~ 'Microsoft.PolicyInsights/PolicyStates'
| extend complianceState = tostring(properties.complianceState)
| extend resourceType = tostring(properties.resourceType)
| where complianceState in ('Compliant', 'NonCompliant')
| summarize
Total = count(),
Compliant = countif(complianceState == 'Compliant'),
NonCompliant = countif(complianceState == 'NonCompliant')
by resourceType
| extend CompliancePercentage = round((Compliant * 100.0) / Total, 2)
| project resourceType, Total, Compliant, NonCompliant, CompliancePercentage
| order by resourceType asc";
// Create the query request
var request = new ResourceQueryContent(query);
// Add each subscription ID individually to the request
foreach (var subscriptionId in subscriptionIds)
{
request.Subscriptions.Add(subscriptionId);
}
// Optional: Add other query options
request.Options = new ResourceQueryRequestOptions
{
Top = 1000, // Limit results if needed
Skip = 0 // For pagination
};
try
{
// Execute the query using the tenant resource
var response = await tenant.GetResourcesAsync(request);
return response.Value;
}
catch (Exception ex)
{
throw new Exception($"Failed to execute Resource Graph query: {ex.Message}", ex);
}
}
// Alternative method to get subscriptions only (useful for testing)
public async Task<List<string>> GetAllSubscriptionIdsAsync()
{
var tenant = _armClient.GetTenants().GetAllAsync().GetAsyncEnumerator().Current;
var subscriptionIds = new List<string>();
await foreach (var subscription in tenant.GetSubscriptions().GetAllAsync())
{
subscriptionIds.Add(subscription.Data.SubscriptionId);
}
return subscriptionIds;
}
}
Make sure you have setup proper controller
[ApiController]
[Route("api/[controller]")]
public class ComplianceController : ControllerBase
{
[HttpGet("score")]
public async Task<IActionResult> GetComplianceScore()
{
try
{
var service = new ComplianceService(
tenantId: "your-tenant-id",
clientId: "your-client-id",
clientSecret: "your-client-secret"
);
var result = await service.GetComplianceScoreAsync();
// Process the results
var complianceData = new List<object>();
foreach (var row in result.Data.Rows)
{
complianceData.Add(new
{
ResourceType = row[0]?.ToString(),
Total = Convert.ToInt32(row[1]),
Compliant = Convert.ToInt32(row[2]),
NonCompliant = Convert.ToInt32(row[3]),
CompliancePercentage = Convert.ToDouble(row[4])
});
}
return Ok(new {
TotalRecords = result.TotalRecords,
Data = complianceData
});
}
catch (Exception ex)
{
return BadRequest($"Error: {ex.Message}");
}
}
}