Skip to content

Commit 1572a04

Browse files
authored
Merge pull request #189271 from JasonAndrewWriter/JA02212022_RESTAPIWalkthrough
Ja02212022 restapi walkthrough transitioning to MSAL
2 parents 667c02f + 7ca6c75 commit 1572a04

File tree

1 file changed

+81
-24
lines changed

1 file changed

+81
-24
lines changed

articles/azure-monitor/essentials/rest-api-walkthrough.md

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ This article shows you how to perform authentication so your code can use the [M
1414

1515
The Azure Monitor API makes it possible to programmatically retrieve the available default metric definitions, dimension values, and metric values. The data can be saved in a separate data store such as Azure SQL Database, Azure Cosmos DB, or Azure Data Lake. From there additional analysis can be performed as needed.
1616

17-
Besides working with various metric data points, the Monitor API also makes it possible to list alert rules, view activity logs, and much more. For a full list of available operations, see the [Microsoft Azure Monitor REST API Reference](/rest/api/monitor/).
17+
Besides working with various metric data points, the Monitor API also makes it possible to list alert rules, view activity logs, and much more. For a full list of available operations, see the [Microsoft Azure Monitor REST API Reference](/rest/api/monitor/).
1818

19-
## Authenticating Azure Monitor requests
20-
21-
The first step is to authenticate the request.
19+
## Authenticating Azure Monitor requests
20+
2221

2322
All the tasks executed against the Azure Monitor API use the Azure Resource Manager authentication model. Therefore, all requests must be authenticated with Azure Active Directory (Azure AD). One approach to authenticate the client application is to create an Azure AD service principal and retrieve the authentication (JWT) token. The following sample script demonstrates creating an Azure AD service principal via PowerShell. For a more detailed walk-through, refer to the documentation on [using Azure PowerShell to create a service principal to access resources](/powershell/azure/create-azure-service-principal-azureps). It is also possible to [create a service principal via the Azure portal](../../active-directory/develop/howto-create-service-principal-portal.md).
2423

@@ -49,29 +48,86 @@ New-AzRoleAssignment -RoleDefinitionName Reader `
4948
5049
```
5150

52-
To query the Azure Monitor API, the client application should use the previously created service principal to authenticate. The following example PowerShell script shows one approach, using the [Active Directory Authentication Library](../../active-directory/azuread-dev/active-directory-authentication-libraries.md) (ADAL) to obtain the JWT authentication token. The JWT token is passed as part of an HTTP Authorization parameter in requests to the Azure Monitor REST API.
51+
To query the Azure Monitor API, the client application should use the previously created service principal to authenticate. The following example PowerShell script shows one approach, using the [Microsoft Authentication Library (MSAL)](/azure/active-directory/develop/msal-overview) to obtain the authentication token.
5352

5453
```powershell
55-
$azureAdApplication = Get-AzADApplication -IdentifierUri "https://localhost/azure-monitor"
56-
57-
$subscription = Get-AzSubscription -SubscriptionId $subscriptionId
58-
59-
$clientId = $azureAdApplication.ApplicationId.Guid
60-
$tenantId = $subscription.TenantId
61-
$authUrl = "https://login.microsoftonline.com/${tenantId}"
62-
63-
$AuthContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]$authUrl
64-
$cred = New-Object -TypeName Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential -ArgumentList ($clientId, $pwd)
65-
66-
$result = $AuthContext.AcquireTokenAsync("https://management.core.windows.net/", $cred).GetAwaiter().GetResult()
67-
68-
# Build an array of HTTP header values
69-
$authHeader = @{
70-
'Content-Type'='application/json'
71-
'Accept'='application/json'
72-
'Authorization'=$result.CreateAuthorizationHeader()
54+
$ClientID = "{client_id}"
55+
$loginURL = "https://login.microsoftonline.com"
56+
$tenantdomain = "{tenant_id}"
57+
$CertPassWord = "{password_for_cert}"
58+
$certPath = "C:\temp\Certs\testCert_01.pfx"
59+
60+
[string[]] $Scopes = "https://graph.microsoft.com/.default"
61+
62+
Function Load-MSAL {
63+
if ($PSVersionTable.PSVersion.Major -gt 5)
64+
{
65+
$core = $true
66+
$foldername = "netcoreapp2.1"
67+
}
68+
else
69+
{
70+
$core = $false
71+
$foldername = "net45"
72+
}
73+
74+
# Download MSAL.Net module to a local folder if it does not exist there
75+
if ( ! (Get-ChildItem $HOME/MSAL/lib/Microsoft.Identity.Client.* -erroraction ignore) ) {
76+
install-package -Source nuget.org -ProviderName nuget -SkipDependencies Microsoft.Identity.Client -Destination $HOME/MSAL/lib -force -forcebootstrap | out-null
77+
}
78+
79+
# Load the MSAL assembly -- needed once per PowerShell session
80+
[System.Reflection.Assembly]::LoadFrom((Get-ChildItem $HOME/MSAL/lib/Microsoft.Identity.Client.*/lib/$foldername/Microsoft.Identity.Client.dll).fullname) | out-null
81+
}
82+
83+
Function Get-GraphAccessTokenFromMSAL {
84+
85+
Load-MSAL
86+
87+
$global:app = $null
88+
89+
$x509cert = [System.Security.Cryptography.X509Certificates.X509Certificate2] (GetX509Certificate_FromPfx -CertificatePath $certPath -CertificatePassword $CertPassWord)
90+
write-host "Cert = {$x509cert}"
91+
92+
$ClientApplicationBuilder = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($ClientID)
93+
[void]$ClientApplicationBuilder.WithAuthority($("$loginURL/$tenantdomain"))
94+
[void]$ClientApplicationBuilder.WithCertificate($x509cert)
95+
$global:app = $ClientApplicationBuilder.Build()
96+
97+
[Microsoft.Identity.Client.AuthenticationResult] $authResult = $null
98+
$AquireTokenParameters = $global:app.AcquireTokenForClient($Scopes)
99+
try {
100+
$authResult = $AquireTokenParameters.ExecuteAsync().GetAwaiter().GetResult()
101+
}
102+
catch {
103+
$ErrorMessage = $_.Exception.Message
104+
Write-Host $ErrorMessage
105+
}
106+
107+
return $authResult
108+
}
109+
110+
function GetX509Certificate_FromPfx($CertificatePath, $CertificatePassword){
111+
#write-host "Path: '$CertificatePath'"
112+
113+
if(![System.IO.Path]::IsPathRooted($CertificatePath))
114+
{
115+
$LocalPath = Get-Location
116+
$CertificatePath = "$LocalPath\$CertificatePath"
117+
}
118+
119+
#Write-Host "Looking for '$CertificatePath'"
120+
121+
$certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertificatePath, $CertificatePassword)
122+
123+
Return $certificate
73124
}
125+
126+
$myvar = Get-GraphAccessTokenFromMSAL
127+
Write-Host "Access Token: " $myvar.AccessToken
128+
74129
```
130+
Loading the certificate from a .pfx file in PowerShell can make it easier for an admin to manage certificates without having to install the certificate in the certificate store. However, this should not be done on a client machine as the user could potentially discover the file and also the password for it, as well as the method to authenticate. The client credentials flow is only intended to be ran in a back-end service to service type of scenario where only admins have access to the machine.
75131

76132
After authenticating, queries can then be executed against the Azure Monitor REST API. There are two helpful queries:
77133

@@ -96,7 +152,8 @@ For example, to retrieve the metric definitions for an Azure Storage account, th
96152
```powershell
97153
$request = "https://management.azure.com/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/azmon-rest-api-walkthrough/providers/Microsoft.Storage/storageAccounts/ContosoStorage/providers/microsoft.insights/metricDefinitions?api-version=2018-01-01"
98154
99-
Invoke-RestMethod -Uri $request `
155+
156+
Invoke-RestMethod -Uri $request `
100157
-Headers $authHeader `
101158
-Method Get `
102159
-OutFile ".\contosostorage-metricdef-results.json" `

0 commit comments

Comments
 (0)