Skip to content

Instantly share code, notes, and snippets.

@ciphertxt
Last active July 14, 2020 17:46
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 ciphertxt/277b03b9a6137d4d4618184dbd4c3991 to your computer and use it in GitHub Desktop.
Save ciphertxt/277b03b9a6137d4d4618184dbd4c3991 to your computer and use it in GitHub Desktop.
Enumerates resources in a subscription and finds diagnostic settings for resources that support them
$currentContext = Get-AzContext
$currentSub = $(Get-AzContext).Subscription.Name
$token = $currentContext.TokenCache.ReadItems() | Where-Object {$_.tenantid -eq $currentContext.Tenant.Id}
$GetScanDetails = @{
Headers = @{
Authorization = "Bearer $($token.AccessToken)"
'Content-Type' = 'application/json'
}
Method = 'Get'
UseBasicParsing = $true
}
# Get unique resources in subscription
$uniqueResources = Get-AzResource | Sort-Object ResourceType -Unique
# Enumerate each resource
foreach ($resource in $uniqueResources) {
Write-Output "ResourceId: $($resource.ResourceId)"
$resourceIdSplit = $resource.ResourceId.Split("/")
# Determine the resource provider for the current resource
$resourceProvider = $resource.ResourceType.ToString().Split("/")[0]
Write-Output "ResourceProvider: $resourceProvider"
$rp = (Get-AzResourceProvider -ProviderNamespace $resourceProvider)
# Retrieve the resource types supported by the resource provider
$rpTypes = $rp.ResourceTypes
# Resource providers have many resource types.
# Based on the current resource ID, drop the resource type and resource name (we'll append the other resource types we find later)
$strToReplace = $resourceIdSplit[$resourceIdSplit.Count - 2] + "/" + $resource.Name
# Enumerate each resource type in the resource provider
Write-Host "Evaluating resource types..."
foreach ($rpType in $rpTypes) {
$tempResourceId = ""
# Build a string for a unique resource ID for each resource type found in the resource provider
if ($rpType.ResourceTypeName -like "*/*") {
$tempResourceId = $resource.ResourceId.Replace($strToReplace, "")
$rpTypeSplit = $rpType.ResourceTypeName.Split("/")
for ($i = 0; $i -lt $rpTypeSplit.Count; $i++) {
if ($i -eq ($rpTypeSplit.Count - 1)) {
$tempResourceId = $tempResourceId + $resource.Name + "/" + $rpTypeSplit[$i]
} else {
$tempResourceId = $tempResourceId + $rpTypeSplit[$i] + "/"
}
}
} else {
$tempResourceId = $resource.ResourceId.Replace($strToReplace, $rpType.ResourceTypeName + "/" + $resource.Name)
}
# Build a string to perform an HTTP get against the management API using the latest API version for the current resource type
$getResourceUri = "https://management.azure.com$($tempResourceId)?api-version=$($rpType.ApiVersions[0])"
Write-Host "`tChecking $($getResourceUri)"
try {
$getResourceStatus = Invoke-WebRequest -Uri $getResourceUri @GetScanDetails
if ($getResourceStatus.StatusCode -eq 200) {
# valid response - parse the resource ID
# all these gets return different schema as it is not standard across RPs :(
if (($getResourceStatus.Content.Length -gt 0) -and ($getResourceStatus.Content -like "*""id"":*")) {
$idStartString = $getResourceStatus.Content.Substring($getResourceStatus.Content.IndexOf("""id"":"))
$idString = $idStartString.Substring(0, $idStartString.IndexOf(",")).Replace("""id"":", "").Replace("""", "").Trim()
# Some RPs return the ID field for non-Azure resources so we'll do a quick check to see if string the string has "subscriptions" in it
if ($idString -like "*/subscriptions/*") {
# Check for diagnostics settings
$getDiagUri = "https://management.azure.com$($idString)/providers/microsoft.insights/diagnosticSettingsCategories/?api-version=2017-05-01-preview"
Write-Host "`t`tChecking $($getDiagUri)"
try {
$getDiagStatus = Invoke-WebRequest -Uri $getDiagUri @GetScanDetails
if ($getDiagStatus.StatusCode -eq 200) {
$Invalid = $False
}
} catch {
# Uncomment below to see actual error. Certain resources are not ResourceTypes that can support Logs and Metrics so the host error is being muted
#write-host $Error[0] -ForegroundColor Red
$Invalid = $True
$Logs = $False
$Metrics = $False
$ResponseJSON = ""
}
if (!($Invalid)) {
$responseDiagJson = $getDiagStatus.Content | ConvertFrom-Json -ErrorAction SilentlyContinue
}
If ($responseDiagJson) {
foreach ($value in $responseDiagJson.value) {
# Throw the response back
$value
}
}
}
}
}
} catch {
# resource has no properties or the call 404'd
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment