Skip to content

Instantly share code, notes, and snippets.

@luckerby
Created December 27, 2020 23:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luckerby/fe94bc40ebc13cf276730d46e3059818 to your computer and use it in GitHub Desktop.
Save luckerby/fe94bc40ebc13cf276730d46e3059818 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Azure.Identity;
using Azure.Storage.Blobs;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Management.ResourceGraph;
using Microsoft.Rest;
using Microsoft.Azure.Management.ResourceGraph.Models;
using Microsoft.Azure.Management.Subscription;
using Microsoft.Azure.Management.Subscription.Models;
using Newtonsoft.Json.Linq;
namespace RetrieveAzureVmData_wFuncAppMI
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task Run([TimerTrigger("0 */15 * * * *")] TimerInfo myTimer, ILogger log)
{
log.LogInformation($"Starting function at: {DateTime.Now}");
string accessToken = await ExtractAccessTokenFromCredentials(
new ManagedIdentityCredential());
await WriteVmDataToStorageAccount(await GetVMData(accessToken, await GetAllAzureSubscriptions(accessToken, log), log));
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
private static async Task<string> ExtractAccessTokenFromCredentials(Azure.Core.TokenCredential tokenCredential)
{
// Extract the access token from the supplied credentials
var accessToken = await tokenCredential.GetTokenAsync(
new Azure.Core.TokenRequestContext(new string[] { "https://management.core.windows.net/.default" }),
new System.Threading.CancellationToken());
return accessToken.Token;
}
private static async Task<List<string>> GetAllAzureSubscriptions(string accessToken, ILogger log)
{
// Pack the credentials in the format required next
ServiceClientCredentials serviceClientCreds = new TokenCredentials(accessToken);
// Get the subscriptions
SubscriptionClient subscriptionClient = new SubscriptionClient(serviceClientCreds);
IEnumerable<SubscriptionModel> allSubscriptions = await subscriptionClient.Subscriptions.ListAsync();
log.LogInformation($"{allSubscriptions.Count()} subscriptions retrieved");
// Extract the subscriptions' ids
List<string> allSubscriptionIds = new List<string>();
foreach (var subscription in allSubscriptions)
{
allSubscriptionIds.Add(subscription.SubscriptionId);
}
return allSubscriptionIds;
}
private static async Task<Newtonsoft.Json.Linq.JArray> GetVMData(string accessToken,
List<string> listOfAllAzureSubscriptionIds, ILogger log)
{
ServiceClientCredentials serviceClientCreds = new TokenCredentials(accessToken);
ResourceGraphClient argClient = new ResourceGraphClient(serviceClientCreds);
string strQuery = @"Resources
| where type =~ 'microsoft.compute/virtualmachines'
| project id, vmId = tolower(tostring(id)), vmName = name
| join (Resources
| where type =~ 'microsoft.network/networkinterfaces'
| mv-expand ipconfig=properties.ipConfigurations
| project vmId = tolower(tostring(properties.virtualMachine.id)), privateIp = ipconfig.properties.privateIPAddress, publicIpId = tostring(ipconfig.properties.publicIPAddress.id)
| join kind=leftouter (Resources
| where type =~ 'microsoft.network/publicipaddresses'
| project publicIpId = id, publicIp = properties.ipAddress
) on publicIpId
| project-away publicIpId, publicIpId1
| summarize privateIps = make_list(privateIp), publicIps = make_list(publicIp) by vmId
) on vmId
| project-away vmId, vmId1
| sort by vmName asc";
QueryRequest request = new QueryRequest();
request.Subscriptions = listOfAllAzureSubscriptionIds;
request.Query = strQuery;
request.Options = new QueryRequestOptions { ResultFormat = ResultFormat.ObjectArray };
JArray allVmData = new JArray();
QueryResponse response;
do
{
response = null;
try
{
response = await argClient.ResourcesAsync(request);
request.Options.SkipToken = response.SkipToken;
}
catch (Exception e)
{
log.LogInformation(e.ToString());
}
log.LogInformation("No of records in current response page: " + response.Count);
allVmData.Merge(response.Data);
} while (!string.IsNullOrEmpty(response.SkipToken));
return allVmData;
}
private static async Task WriteVmDataToStorageAccount(Newtonsoft.Json.Linq.JArray allVmData)
{
string blockBlobName = "azureVMs.json";
// Hard-coded connection string below. It would be ideal to read this from Azure Vault
var connectionString = "STORAGE_ACCOUNT_CONNECTION_STRING";
// Build the object that will connect to the container within our target storage account
BlobContainerClient blobContainerClient = new BlobContainerClient(connectionString, "STORAGE_ACCOUNT_CONTAINER_NAME");
// Write to Azure Blob Storage
BlobClient blobClient = blobContainerClient.GetBlobClient(blockBlobName);
using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(allVmData.ToString())))
{
await blobClient.UploadAsync(memoryStream, true);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment