Azure Policy API not supplying me with valid Non-Compliant Resource or Policies with PowerShell

Hopefully, someone can assist. Ideally this is the 2nd time I have worked with Azure APIs - in more of a sysadmin role vs Developer.

Essentially what I want is to export the Non-Compliance Microsoft Azure Policies to a HTML report, there is no currently way of doing this so worked on my own method.

Connecting to the PolicyAssignments API I have been successfully able to export the: Azure Policy Names, Azure Policy Descriptions however not the Non Compliant resources or policies. Essentially what I am getting back is a '0', which although is really nice! I know it not to be the truth!

Attached to this post is a screenshot of the HTML export I have managed to do, but don't understand why the Resources & Policies are all coming up as '0'.

This is the code I have so far:

$PolicyResults = @()
ForEach ($subid in $subscriptionId)

{

    $Headers = @{
        'authorization' = "Bearer $token"
        'host'          = 'management.azure.com'
        'contentype'    = 'application/json'
    }


    $url = "https://management.azure.com/subscriptions/$subid/providers/Microsoft.Authorization/policyAssignments?api-version=2017-06-01-preview"


    $policies = Invoke-RestMethod  -Uri $url  -Headers $Headers -Method Get

ForEach ($policy in $policies.value) {

    $id = $policy.name
    $resources = "https://management.azure.com/subscriptions/$subid/providers/Microsoft.Authorization/policyDefinitions/$id/providers/Microsoft.PolicyInsights/policyStates/latest/summarize?api-version=2017-12-12-preview&filter=IsCompliant eq false"


    $a = Invoke-RestMethod  -Uri $resources  -Headers $Headers -Method Post

    ForEach ($value in $a.value)
    {
        $PolicyResults += [pscustomobject]@{
            'Policy Name' = ($policy.properties.displayName)
            'Policy Description' = ($policy.properties.description)
            'Non Compliant Resources'  = ($value.Results.NonCompliantResources)
            'Non Compliant Policies' = ($value.Results.NonCompliantPolicies)
        }
    }


}
}

Open in new window


I am hoping someone can try and replicate my issues and help point me in the right direction. I believe the problem is with the $resources variable but uncertain, have also tried removing the filter and no change.
Genesis Energy C&EAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kyle SantosSoftware Test Analyst I at Dassault SystemesCommented:
Hi,

I am here to help you with your open question.  Do you still need help?  I have the ability to alert more experts if you still need help.

If you solved the problem on your own, would you please post the solution here in case others have the same problem?

If you need me to delete this question just say "Delete."

Thank you for using Experts Exchange.

Regards,

Kyle Santos
Customer Relations
Genesis Energy C&EAuthor Commented:
Thanks, unfortunately still having a bit of problems, so any help would be appreciated.
Chinmay PatelChief Technology NinjaCommented:
Hi,

Please attach the screenshot as it has not come through.
Also, can you please confirm this is similar to the version of Policy API described here:
https://docs.microsoft.com/en-us/azure/azure-policy/policy-compliance#portal?

# Login first with Connect-AzureRmAccount if not using Cloud Shell

$azContext = Get-AzureRmContext
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
$profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile)
$token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId)
$authHeader = @{
    'Content-Type'='application/json'
    'Authorization'='Bearer ' + $token.AccessToken
}

# Define the REST API to communicate with
# Use double quotes for $restUri as some endpoints take strings passed in single quotes
$restUri = "https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.PolicyInsights/policyStates/latest/summarize?api-version=2018-04-04"

# Invoke the REST API
$response = Invoke-RestMethod -Uri $restUri -Method POST -Headers $authHeader

# View the response object (as JSON)
$response

Open in new window


If yes, can you tweak it and see if it still works for you. especially api-version=2018-04-04 part along with the necessary filters that you need. If it works then I will be able to provide you the formate you are looking for.

Regards,
Chinmay.
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

Kyle SantosSoftware Test Analyst I at Dassault SystemesCommented:
Genesis-EnergyCE,

An expert has replied.

Is there anything else we may assist you with?

Regards,

Kyle Santos
Customer Relations
Genesis Energy C&EAuthor Commented:
Thanks, Chinmay. Yes that looks right - will give it a try tonight. Don't have the code with me at work currently and let you know how I get on. Thanks for the assistance.
Genesis Energy C&EAuthor Commented:
Hey, Chinmay

Switched to the 2018 API but same issue.

I am able to connect, and get the Policy Name and Description, but the compliance data doesn't seem to be working.

Current script:

$result = Invoke-RestMethod -Uri https://login.microsoftonline.com/$TENANTID/oauth2/token?api-version=1.0 -Method Post -Body @{
  'grant_type'  = 'client_credentials'
  'resource'    = 'https://management.core.windows.net/'
  'client_id'   = "$APPID"
  'client_secret' = "$PASSWORD"
}
$token = $result.access_token

#Sets CSS
$Css = '<style>table{margin:auto; width:98%}
  body{background-color:#fffffF    ; text-align:Center; font-family: Calibri ;}
  p,h2{text-align:Center; font-family: Calibri ;}
  h1 {text-align:Center; font-family: Circular Pro Black; font-weight: bold; color:#464958
  ;  }
  th{background-color:#464958; color:white;}
td{background-color:lightgrey; color:#464958  ; Text-align:Center;} </style>'

##set subscriptionId

$subscriptionId= @('0000000000000000000000', '0000000000000000000000', '0000000000000000000')


$PolicyResults = @()
ForEach ($subid in $subscriptionId)

{

    $Headers = @{
        'authorization' = "Bearer $token"
        'host'          = 'management.azure.com'
        'contentype'    = 'application/json'
    }


    $url = "https://management.azure.com/subscriptions/$subid/providers/Microsoft.Authorization/policyAssignments?api-version=2017-06-01-preview"


    $policies = Invoke-RestMethod  -Uri $url  -Headers $Headers -Method Get

ForEach ($policy in $policies.value) {

    $id = $policy.name
    $resources = "https://management.azure.com/subscriptions/$subid/providers/Microsoft.Authorization/policyDefinitions/$id/providers/Microsoft.PolicyInsights/policyStates/latest/summarize?api-version=2018-04-04"


    $a = Invoke-RestMethod  -Uri $resources  -Headers $Headers -Method Post

    ForEach ($value in $a.value)
    {
        $PolicyResults += [pscustomobject]@{
            'Policy Name' = ($policy.properties.displayName)
            'Policy Description' = ($policy.properties.description)
            'Non Compliant Resources'  = ($value.Results.NonCompliantResources)
            'Non Compliant Policies' = ($value.Results.NonCompliantPolicies)
        }
    }


}
}

$PolicyResults  | ConvertTo-HTML -head "$css <H1> Microsoft Azure Policy Report</H1>" -Title 'Microsoft Azure Policy Report'  | Out-File -FilePath C:\temp\AzurePolicy.html

Open in new window


Example of output:

Azure Policy Report Export
Chinmay PatelChief Technology NinjaCommented:
Hi,

I would like to check Output of
$a = Invoke-RestMethod  -Uri $resources  -Headers $Headers -Method Post

Open in new window


Have you tried dumping $a as it is or by debugging the script? If you can please save $a as a plain text and check if we are getting the results from the query or not.

Regards,
Chinmay.
Genesis Energy C&EAuthor Commented:
The variable is a large object, compartmentalized. Its all '0' in the object, however there is definitely non-compliant resources in the Azure portal.
Genesis Energy C&EAuthor Commented:
I noticed that in the query results variable the results have:

 /providers/Microsoft.Authorization/policyDefinitions/SecurityCenterBuiltIn/providers/Microsoft.PolicyInsights/policyStates/latest/queryResults?api-version=2018-04-04&$from=2018-08-12 09:33:09Z&$to=2018-08-13 09:33:09Z&$filter=IsCompliant eq false; nonCompliantResources=0; nonCompliantPolicies=0}

Not sure if this has altered the results.
Chinmay PatelChief Technology NinjaCommented:
Hi,

I would like to see the definition of your policy. Any one policy - sanitize your screen shot and post it here please.
Also the list of policies from the Azure portal which are being reported as compliance violation, post a screenshot of that as well.

https://portal.azure.com/#blade/Microsoft_Azure_Policy/PolicyMenuBlade/Compliance
Kyle SantosSoftware Test Analyst I at Dassault SystemesCommented:
Genesis-EnergyCE,

An expert has replied.

Is there anything else we may assist you with?

Regards,

Kyle Santos
Customer Relations
Genesis Energy C&EAuthor Commented:
Thanks guys. Just closing this question, cheers for the help!
Kyle SantosSoftware Test Analyst I at Dassault SystemesCommented:
Hi,

Here are steps on how to close your question.
http://support.experts-exchange.com/customer/portal/articles/2527982-how-do-i-close-my-question-

Or just let me know whose answer was the best and which were helpful.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.