Storage REST API Returns Remote Name Could Not be Resolve Often - azure

I am calling the storage REST API to get container names using
Invoke-WebRequest -Method GET -Uri $storage_url -Headers $headers
This command often returns 'remote name could not be resolved error', even when the storage account exists and is reachable. Just running the command again gives correct result.
Invoke-WebRequest : The remote name could not be resolved: '<storageAccountName>.blob.core.windows.net'
At line:1 char:1
+ Invoke-WebRequest -Method GET -Uri $storage_url -Headers $headers #In ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

From the information you provided, you use the client credential flow to get the access token, then use the token to call the Storage Rest API - List Containers.
You could use the script below, it works for me.
Make sure the service principal you used has a RBAC role e.g. Contributor/Owner in your storage account -> Access Control, if not, click the Add to add it.
$ClientID = "xxxxxxx"
$ClientSecret = "xxxxxxx"
$tennantid = "xxxxxxx"
$storageaccountname = "joystoragev2"
$TokenEndpoint = {https://login.microsoftonline.com/{0}/oauth2/token} -f $tennantid
$Resource = "https://storage.azure.com/"
$Body = #{
'resource'= $Resource
'client_id' = $ClientID
'grant_type' = 'client_credentials'
'client_secret' = $ClientSecret
}
$params = #{
ContentType = 'application/x-www-form-urlencoded'
Headers = #{'accept'='application/json'}
Body = $Body
Method = 'Post'
URI = $TokenEndpoint
}
$token = Invoke-RestMethod #params
$accesstoken = $token.access_token
$url = {https://{0}.blob.core.windows.net/?comp=list} -f $storageaccountname
$header = #{
'Authorization' = 'Bearer ' + $accesstoken
'x-ms-version' = '2019-02-02'
}
$response = Invoke-WebRequest –Uri $url –Headers $header –Method GET
$response.RawContent

Related

Azure Databricks API

Trying to use the Databricks API to work with resources programmatically. I am using this microsoft documentto authenticate with a service principal.
https://learn.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/aad/service-prin-aad-token
But I'm getting the following error
"Invoke-RestMethod : {"error":"invalid_resource","error_description":"AADSTS500011: The resource principal named
https://management.core.azure.com was not found in the tenant"
This is my full script. What am I missing?
$ApiCommand = "clusters/get"
$DataBrick = "https://adb-3522222096750220.0.azuredatabricks.net"
$DataBricksResourceID = ""
$VaultName = ""
$KeyName = ""
$apiEndpointUri = "https://management.core.azure.com"
$tenantId = ""
$applicationId = ""
$secret = Get-AzKeyVaultSecret -VaultName $VaultName -Name $KeyName -AsPlainText
$RequestAccessTokenUri = "https://login.microsoftonline.com/$tenantId/oauth2/token"
$body = "grant_type=client_credentials&client_id=$applicationId&client_secret=$secret&resource=2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"
$Managementbody = "grant_type=client_credentials&client_id=$applicationId&client_secret=$secret&resource=$apiEndpointUri"
$contentType = 'application/x-www-form-urlencoded'
$AccessToken = Invoke-RestMethod -Method Post -Uri $RequestAccessTokenUri -Body $body -ContentType $contentType
Write-Output $AccessToken
$ManagementToken = Invoke-RestMethod -Method Post -Uri $RequestAccessTokenUri -Body $Managementbody -ContentType $contentType
Write-Output $ManagementToken
$apiuri = $DataBrick +"/api/2.0/$ApiCommand"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer " + $AccessToken.access_token)
$headers.Add("X-Databricks-Azure-SP-Management-Token", $ManagementToken.access_token)
$headers.Add("X-Databricks-Azure-Workspace-Resource-Id", $DataBricksResourceID)
Invoke-RestMethod -Uri $apiuri -Headers $headers
The trailing / character in the management endpoint URI is really important - you need to specify it as in the documentation: https://management.core.windows.net/
You can also add this SP into the workspace itself, then you will need to get only one AAD token (see the docs).

Using Azure Yaml pipeline to call powershell RestMethod with secret variable in body

I am trying to automate a step in our Azure yaml pipeline to delete some users from Auth0 using PowerShell and RestMethod, but for some reason the secret is either not used correctly or changed or something.
I have set the secret as a variable and then tried using it either directly in the script or through setting it on the task as well as an environment variable, but no luck.
Here is my last iteration, but still no joy, could anyone shed some light on the issue?
$api = "api/v2/"
$audience = $audience + $api
$secret = "$env:AUTH0_CLIENT_SECRET"
$test = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($secret))
Write-Host $clientSecret.substring(0,10)
Write-Host $test.substring(0,10)
Write-Host $audience
Write-Host $clientId
$Body = #{
client_id = $clientId
client_secret = $test OR $secret OR $clientSecret
audience = $audience
grant_type = "client_credentials"
}
Write-Host 'Getting token'
$response = Invoke-RestMethod https://mytenant.eu.auth0.com/oauth/token `
-Method 'POST' `
-ContentType 'application/json; charset=utf-8' `
-Body ($Body | ConvertTo-Json)
As shown, I have tried using test, secret and clientSecret as the secret, but also no luck. The write host at the start does show the correct starting characters for $clientSecret
Am I missing something basic or is this just not possible using RestMethod?
Ended up going scorched earth and completely deleted the pipelines and started again, this is the powershell script I ended up with that worked.
$token = "/oauth/token"
$https = "https://"
$api = "/api/v2/"
$audience = $https + $domain + $api
$tokenUrl = $https + $domain + $token
Write-Host 'Getting token'
$response = Invoke-RestMethod $tokenUrl `
-Method 'POST' `
-ContentType 'application/json; charset=utf-8' `
-Body (#{
client_id = $clientId
client_secret = "$env:AUTH0_CLIENT_SECRET"
audience = $audience
grant_type = "client_credentials"
} | ConvertTo-Json)

calling azure graph api to fetch Get-PimAzureResourceRoleDefinition

I am trying to a call graphapi to get roledefination but i am getting permission errors, and have i checked my service prnciple it had all required permissions.
Invoke-RestMethod : {
"error": {
"code": "UnknownError",
"message": "{\"errorCode\":\"PermissionScopeNotGranted\",\"message\":\"Authorization failed due to missing permission scope PrivilegedAccess.ReadWrite.AzureResources,PrivilegedAccess.Read.AzureResources.\",\"target\":null,\"details\":null,\"innerError\":null,\"instanceAnnotations\":[],\"typeAnnotation\":null}",
"innerError": {
"request-id": "d762f8d4-2cc4-428e-b1ea-7623d8d388f1",
"date": "2020-06-03T04:25:03"
}
}
}
At line:38 char:15
+ $Result = Invoke-RestMethod -Uri $uri -Headers $Headers
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Below is my code
========================
$TenantName = 'xxxx.onmicrosoft.com'
$ClientId = 'xxxxxx'
$ClientSecret = "xxxxxx"
# Create a hashtable for the body, the data needed for the token request
# The variables used are explained above
$Body = #{
'tenant' = $TenantId
'client_id' = $ClientId
'scope' = 'https://graph.microsoft.com/.default'
'client_secret' = $ClientSecret
'grant_type' = 'client_credentials'
}
$Params = #{
'Uri' = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
'Method' = 'Post'
'Body' = $Body
'ContentType' = 'application/x-www-form-urlencoded'
}
$AuthResponse = Invoke-RestMethod #Params
$Headers = #{
'Authorization' = "Bearer $($AuthResponse.access_token)"
}
#Find Pim Role
$uri = "https://graph.microsoft.com/beta/privilegedAccess/azureResources/resources/xxxxxxxxxxxx/roleDefinitions`?`$filter=displayName eq 'xxxxxx-Contributors'"
$Result = Invoke-RestMethod -Uri $uri -Headers $Headers
Also how to get resource id of roledefination which we are passing in URL after /resources
Check your Api permissions, make sure the PrivilegedAccess.Read.AzureResources is selected and click the button Grant admin consent for xxx.
You could decode your access_token via https://jwt.io/, scp shows your scopes.
Update:
how to get resource id of roledefination which we are passing in URL after /resources
try request this:
GET https://graph.microsoft.com/beta/privilegedAccess/azureResources/resources

Microsoft Graph - Grant_Type client_credentials calendarview - Access is denied. Check credentials and try again

I am using PowerShell to get Calendar events from MS Graph.
Grant Type: client_credentials
$clientId = "xxx"
$tenantName = "xxx"
$clientSecret = "xxx"
$resource = "https://graph.microsoft.com/"
$ReqTokenBody = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
client_Id = $clientID
Client_Secret = $clientSecret
}
$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
Grant Type: Password
$clientID = "xxx"
$tenantName = "xxx"
$ClientSecret = "xxx"
$Username = "xxx#xxx.com"
$Password = "xxx"
$ReqTokenBody = #{
Grant_Type = "Password"
client_Id = $clientID
Client_Secret = $clientSecret
Username = $Username
Password = $Password
Scope = "https://graph.microsoft.com/.default"
}
$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
Get Calendar Events:
$apiUrl = "https://graph.microsoft.com/v1.0/groups/xxxxxxxxxx/calendarview?startdatetime=$mystartdate1&enddatetime=$myenddate1&orderby=start/DateTime ASC&top=100"
$Data = Invoke-RestMethod -Headers #{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $apiUrl -Method Get
$Groups = ($Data | select-object Value).Value
#$Groups | Format-Table subject, start -AutoSize
$Groups | Select-Object -Property subject, Start, End
If I authenticate by Password Grant Type then it displays the results.
However if I authenticate by Client Credentials Grant Type then it throws following error:
Invoke-RestMethod : {
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "cc111097-c8c2-4a35-af21-52cbbced33b7",
"date": "2019-11-29T09:37:51"
}
}
}
At line:10 char:9
+ $Data = Invoke-RestMethod -Headers #{Authorization = "Bearer $($Token ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
With the Client Credentials Grant Type I have no problem getting results from
$apiUrl = "https://graph.microsoft.com/v1.0/users/"
$apiUrl = 'https://graph.microsoft.com/v1.0/groups'
$apiUrl = "https://graph.microsoft.com/v1.0/devicemanagement/manageddevices"
Am I doing something wrong or the client credentials authentication cannot pull the calendar events.
When using the client credential flow to get the access token for Microsoft Graph, the Application permission in your AD App -> API permissions is needed.
But in this case, the Application permission is not supported for the List calendarView API. Without this permission, the token you got will not be able to call this API successfully.

Can I use MFA app passwords with Azure oauth2.0 ROPC?

In powershell we have a script that gets info from Azure REST API using Resource Owner Password Credentials.
https://learn.microsoft.com/bs-latn-ba/azure/active-directory/develop/v2-oauth-ropc
The script works perfectly with users that don't have MFA enabled. For user with MFA it doesn't work.
I tried to use an app password that I created on the user account with MFA but this didn't work also.
https://support.microsoft.com/en-au/help/12409/microsoft-account-app-passwords-and-two-step-verification
The script is running as a service so user interaction is no option. We also need to use ROPC because the info we needed is only available trough delegated permisions on the Azure app.
Is there anyone that has experience with this?
Here is the script:
$tenantid = '*************************'
$subscriptionid = '*********************'
$clientid = '***********************'
$clientsecret = '******************'
$username = '*****************'
$password = '************************'
##################################################################
##################################################################
##################################################################
$return = Invoke-Command -ScriptBlock {
param($tenantid,$subscriptionid,$clientid,$clientsecret,$username,$password)
Add-Type -AssemblyName System.Web
$encPass = [System.Web.HttpUtility]::UrlEncode($password)
$encScope = [System.Web.HttpUtility]::UrlEncode('https://management.azure.com/user_impersonation')
$encSecret = [System.Web.HttpUtility]::UrlEncode($clientsecret)
$body = "client_id=$clientid&scope=$encScope&username=$username&password=$encPass&grant_type=password&client_secret=$encSecret"
$auth = Invoke-WebRequest "https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token" -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing
$token = ($auth | ConvertFrom-Json).access_token
$headers = #{
'Authorization'="Bearer $($token)"
}
$data = Invoke-WebRequest "https://management.azure.com/subscriptions/$subscriptionid/providers/Microsoft.Advisor/recommendations?api-version=2017-04-19" -Method GET -Headers $headers -UseBasicParsing
New-Object PSObject -Property #{
content=$data.content
}
} -ArgumentList $tenantid,$subscriptionid,$clientid,$clientsecret,$username,$password
$content = $return.content
Write-Host $content
The output when I use an user with MFA enabled:
Invoke-WebRequest : {"error":"invalid_grant","error_description":"AADSTS50076: Due to a configuration change made by your administrator, or because you moved to a new location, you must use multi-factor authentication to
access '*******'.\r\nTrace ID: d9a7f9f2-c52c-40ca-b057-9513bd353900\r\nCorrelation ID: 3329e686-7bd0-409d-b7da-91e49221bacc\r\nTimestamp: 2019-10-02
13:19:36Z","error_codes":[50076],"timestamp":"2019-10-02
13:19:36Z","trace_id":"d9a7f9f2-c52c-40ca-b057-9513bd353900","correlation_id":"3329e686-7bd0-409d-b7da-91e49221bacc","error_uri":"https://login.microsoftonline.com/error?code=50076","suberror":"basic_action"}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:27 char:9
+ $auth = Invoke-WebRequest "https://login.microsoftonline.com/$tenanti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:29 char:19
+ $token = ($auth | ConvertFrom-Json).access_token
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
Invoke-WebRequest : {"error":{"code":"AuthenticationFailedMissingToken","message":"Authentication failed. The 'Authorization' header is missing the access token."}}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:34 char:9
+ $data = Invoke-WebRequest "https://management.azure.com/subscriptions ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
The output when I change the password with an app password created on the user account
Invoke-WebRequest : {"error":"invalid_grant","error_description":"AADSTS50126: Invalid username or password.\r\nTrace ID: 3674934a-120b-48f3-96d8-7ec8ddf44300\r\nCorrelation ID:
593aecd7-bbb2-4c5a-96e1-050bc00047ac\r\nTimestamp: 2019-10-02 13:26:46Z","error_codes":[50126],"timestamp":"2019-10-02
13:26:46Z","trace_id":"3674934a-120b-48f3-96d8-7ec8ddf44300","correlation_id":"593aecd7-bbb2-4c5a-96e1-050bc00047ac","error_uri":"https://login.microsoftonline.com/error?code=50126"}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:27 char:9
+ $auth = Invoke-WebRequest "https://login.microsoftonline.com/$tenanti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:29 char:19
+ $token = ($auth | ConvertFrom-Json).access_token
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
Invoke-WebRequest : {"error":{"code":"AuthenticationFailedMissingToken","message":"Authentication failed. The 'Authorization' header is missing the access token."}}
At C:\Users\Wouter.sterkens\Documents\VS Projects\Azure Monitoring\advisor.ps1:34 char:9
+ $data = Invoke-WebRequest "https://management.azure.com/subscriptions ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
As far as I know, app password is used to complete MFA with the clients which do not support modern authentication. Now, you use ROPC OAuth flow. APP password does not support it.
According to the situation, I suggest you finish MFA manually to get refresh token then we use refresh token to get access token and call API. Because MFA refresh token will not expire until you revoke it. Or you use OAuth 2.0 client credentials flow to get the access token. For example
User refresh token
Register Azure AD application
Use OAuth 2.0 authorization code flow to complete MFA and get refresh token
$Params = #{
'client_id' = 'b0114608-677e-4eca-ae22-60c32e1782d9'
'redirect_URI' = 'https://www.baidu.com'
'response_type'='code'
'scope' = 'offline_access openid https://management.azure.com/user_impersonation'
}
$ClientSecret =''
$TeantID = ''
$Query = "?"; $Params.Keys | % {$Query+= "$($_)=$($Params.Item($_))&"} ; $Query = $Query.TrimEnd('&')
$IE= new-object -ComObject "InternetExplorer.Application"
$IE.Visible = $true
$IE.navigate2("https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/authorize$Query")
write-host "get authorization code"
pause
Add-Type -AssemblyName System.Web
[System.Web.HttpUtility]::ParseQueryString(([uri] $IE.LocationURL).Query)['code']
$Code = [System.Web.HttpUtility]::ParseQueryString(([uri] $IE.LocationURL).Query)['code']
$IE.Quit()
$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body #{
client_id = $Params.client_id
scope = ''
code = $Code
redirect_uri = $Params.Redirect_URI
grant_type = 'authorization_code'
client_secret = $ClientSecret
}
$TokenResult.refresh_token
Get Access token and call the api
$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body #{
client_id = ''
scope = 'https://management.azure.com/user_impersonation'
redirect_uri = ''
grant_type = 'refresh_token'
client_secret = ''
refresh_token =''
}
Invoke-RestMethod -Method Get -Uri '' -Headers #{Authorization = "Bearer "+ $TokenResult.access_token}
Use OAuth 2.0 client credentials flow
$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body #{
client_id = ''
scope = 'https://management.azure.com/.default'
grant_type = 'client_credentials'
client_secret = ''
}
Invoke-RestMethod -Method Get -Uri '' -Headers #{Authorization = "Bearer "+ $TokenResult.access_token}
Update
According to your need, you can create a service principal and assign RABC role to the service principal. Then you can OAuth 2.0 client credentials flow to get access token and call Azure rest api. The detailed steps are as below
Create a service principal and assign RABC role to the service principal
Connect-AzAccount
$password=''
$credentials = New-Object Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential -Property #{ StartDate=Get-Date; EndDate=Get-Date -Year 2024; Password=$password'}
$sp = New-AzAdServicePrincipal -DisplayName jimtest1 -PasswordCredential $credentials
New-AzRoleAssignment -ApplicationId $sp.ApplicationId -RoleDefinitionName Owner
Get access token
# get access token
$TeantID='hanxia.onmicrosoft.com'
$TokenResult = Invoke-RestMethod -Method Post -ContentType 'application/x-www-form-urlencoded' -Uri "https://login.microsoftonline.com/$($TeantID)/oauth2/v2.0/token" -Body #{
client_id = $sp.ApplicationId # the application id of service principal
scope = 'https://management.azure.com/.default'
grant_type = 'client_credentials'
client_secret = $password # you use it in step 1
}
Call Azure Rest API
#list resource group
$values =Invoke-RestMethod -Method Get -Uri "https://management.azure.com/subscriptions/e5b0fcfa-e859-43f3-8d84-5e5fe29f4c68/resourcegroups?api-version=2019-05-10" -Headers #{
Authorization = "Bearer "+ $TokenResult.access_token
ContentType = 'application/json'
}
For more details, please refer to
https://learn.microsoft.com/en-us/powershell/azure/create-azure-service-principal-azureps?view=azps-2.7.0
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-api-authentication#get-app-only-access-token-for-azure-resource-manager

Resources