Is it possible to update URL is availability test in application insights through powershell on a schedule task/frequency - azure

I have a number of environments in azure which utilize on-premise Restful services for one of our customers. We currently have application insights configured within a resource group, and an availability test configured to ping a URL at a specified frequency, configured with an insights alert (email when goes down)
An access token is embedded into the URL which needs to be updated frequently. Is it possible to update the URL highlighted programmatically to replace the token (Scheduled/automated basis )
Just wondering what technologies could be used to update an availability URL on a scheduled basis (every two weeks)
Azure functions?
Some sort of PowerShell script as a scheduled task?
ARM templates using the example here https://learn.microsoft.com/en-us/azure/azure-monitor/app/powershell#add-an-availability-test
Any advice on how to proceed with this task efficiently and using the most appropriate technologies would be appreciated.

I have to say seems there is no PowerShell module provided to modify the url of App Insight webtest , but we can do it via REST API . Try the PowerShell below :
$clientId = "<your Azure AD application ID>"
$clientSec="<your Azure AD application secret>"
$appInsightName ="<your app insight name>"
$webtestName="<your webtest name>"
$subscriptionId = "<your subscription ID>"
$resourceGroupName = "<your resource group name that your app insight in>"
$tenant = "<your tenant name/ID>"
$newUrl = "<the new URL>"
#get access token to fetch details of webtest
$body=#{
    "grant_type"="client_credentials";
    "resource"="https://management.azure.com/";
    "client_id"= $clientId;
    "client_secret" = $clientSec
}
$accessToken=(Invoke-RestMethod -Uri "https://login.windows.net/$tenant/oauth2/token" -Method POST -Body $body ).access_token
$uri = "https://management.azure.com/subscriptions/{0}/resourcegroups/{1}/providers/microsoft.insights/webtests/{2}-{3}?api-version=2015-05-01"
$uri = $uri.Replace("{0}",$subscriptionId).Replace("{1}",$resourceGroupName).Replace("{2}",$webtestName).Replace("{3}",$appInsightName)
$webtestResult = Invoke-RestMethod -Uri $uri -Method GET -Headers #{"Authorization"="Bearer $accessToken"}
#modify the url of webtest
$webTestConf = [xml]#($webtestResult.properties.Configuration.WebTest)
$webTestConf.WebTest.Items.Request.Url = $newUrl
#structure request json to update webtest
$locations = $webtestResult.properties.Locations | ConvertTo-Json
$Configuration = $webTestConf.WebTest.OuterXml | ConvertTo-Json
$Configuration = $Configuration.Replace("\u003c","<").replace("\u003e",">")
$location = $webtestResult.location
$tags = $webtestResult.tags| ConvertTo-Json
$name = $webtestResult.properties.Name
$kind = $webtestResult.properties.Kind
$json = #"
{
"location":"$location",
"tags":$tags,
"properties":{
"Name":"$name",
"Enabled": true,
"Frequency": 300,
"Timeout": 120,
"Locations":$locations,
"Configuration":{"webtest":$Configuration},
"Kind":"$kind"
}
}
"#
Invoke-RestMethod -Uri $uri -Method PUT -Body $json -Headers #{"Authorization"="Bearer $accessToken";"Content-Type"="application/json"}
Except for Azure function, you can use Azure automation powershell Runbook with scheduled task to meet your requirement .
Btw, this powershell demo uses service principle to connect to your Azure subscription, make sure your Azure ad application has permission to modify your app insight. If you have anything unclear , pls feel free to let me know . This issue shall not be passed !

Related

Azure AutomationAccount DSC scripts debug

I am running a DSC script from an Azure automation account to configure Windows VMs. It downloads files from a storage account in Azure to hosts for more configurations. If I hardcode the storage SAS token, it works fine. But I would like to get the SAS token in the DSC script. I use managed identity of the Automation account and assigned proper IAM access in storage account. I am able to get the SAS token in a test runbook script, but not in DSC script.
I got the main part of the code from
https://learn.microsoft.com/en-us/azure/automation/enable-managed-identity-for-automation
The error I am getting indicates that the SAS token is not generated correctly, but I can't find a way to see what the error msgs are from this part of the code in DSC when it executed.
any help/suggestion is appreciated!
Configuration DSCtest {
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
$resource= "?resource=https://management.azure.com/"
$url = $env:IDENTITY_ENDPOINT + $resource
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("X-IDENTITY-HEADER", $env:IDENTITY_HEADER)
$Headers.Add("Metadata", "True")
$accessToken = Invoke-RestMethod -Uri $url -Method 'GET' -Headers $Headers
$Atoken = $accessToken.access_token
Write-Output $Atoken
$toDate = (Get-Date).AddDays(4).toString("yyyy-MM-ddT00:00:00Z")
$params = #{canonicalizedResource="/file/storageacnt/exec";signedResource="c";signedPermission="rcw";signedProtocol="https";signedExpiry=$toDate}
$jsonParams = $params | ConvertTo-Json
$sasResponse = Invoke-WebRequest -Uri https://management.azure.com/subscriptions/xxxxxxxxxxxx/resourceGroups/rg-xxxxx/providers/Microsoft.Storage/storageAccounts/storageaccnt/listServiceSas/?api-version=2017-06-01 -Method POST -Body $jsonParams -Headers #{Authorization="Bearer $Atoken"} -UseBasicParsing
$sasContent = $sasResponse.Content | ConvertFrom-Json
$sasCred = $sasContent.serviceSasToken
write-host $sasCred
$sasToken = "?$sasCred"
Node LocalHost {
....

How to manage the Azure APIM developer portal delegation with Azure PowerShell

I want to enable the Azure APIM developer portal sign-in & sign-up delegation and to generate a "Delegation Validation Key". This is straightforward with the Azure portal:
I want to achieve the same thing but with Azure PowerShell as part of a bigger deployment pipeline.
I cannot find any documentation on how to do that.
Thanks
AFAIK, We can not achieve the above requirement using powershell , Here are the details (MICROSOFT DOCUMENTATION) for what we can configure through powershell for APIM .
Instead of that we can configure the above requirement using git , Please refer this MICRSOFT DOCUMENTATION for more details & the list of cmdlets for APIM .
An additional option is to use an HTTP call against the resource. The call can be made with the PowerShell script as well.
This can be done as follows:
Get an Azure access token - you should have a Service Principal with sufficient permissions for the resource we are going to deal with.
$tokenUri = "https://login.microsoftonline.com/${tenantId}/oauth2/token"
$form = #{
grant_type = 'client_credentials'
resource = 'https://management.core.windows.net/'
client_id = $spClientId
client_secret = $spClientSecret
}
$response = Invoke-RestMethod -Uri $tokenUri -Method Post -Body $form
$azureToken = $response.access_token
Send an HTTP request against the APIM service
$url = "https://management.azure.com/subscriptions/${subscriptionId}/resourceGroups/${apiManagementRg}/providers/Microsoft.ApiManagement/service/${apiManagementName}/portalsettings/delegation?api-version=2020-12-01"
$headers = #{ 'Authorization' = "Bearer ${azureToken}" }
$body = #"
{
"properties": {
"url": "$delegationUrl",
"validationKey": "$validationKey",
"subscriptions": {
"enabled": false
},
"userRegistration": {
"enabled": true
}
}
}
"#
$delegationResponse = Invoke-RestMethod -Method 'Put' -Body $body -Uri $url -Headers $headers

How to get thumbprint of the certificate associated with a service principal using Powershell?

I have a certificate associated with a service principal in Azure AD. How can I get the certificate name or thumbprint associated with it using powershell?
I have tried Get-AzureRmADServicePrincipalCredential, Get-AzureRmADSpCredential and Get-AzureADServicePrincipalKeyCredential commands but they return Key Identifier not thumbprint.
Basically I want to recognize which certificate is associated with the principal before revoking it.
As #Stanley Gong mentioned, you can use MS Graph to get it.
Here is another way, try the command as below, the $Thumbprint is that you want.
Note the <object-id> is the object id of your AD App(App registration), not the service principal(Enterprise application), they are different.
$CustomKeyIdentifier = (Get-AzureADApplicationKeyCredential -ObjectId "<object-id>").CustomKeyIdentifier
$Thumbprint = [System.Convert]::ToBase64String($CustomKeyIdentifier)
Try the PS command below to get cert thumbprint via Microsoft Graph API :
$clientId = "<your Azure AD App ID>"
$clientSec="<your Azure AD App Secret>"
$appObjId = "<object ID of the app that you want to query>"
$tenant = "<your tenant ID>"
$body=#{
    "grant_type"="client_credentials";
    "resource"="https://graph.microsoft.com/";
    "client_id"= $clientId;
    "client_secret" = $clientSec
}
$accessToken=(Invoke-RestMethod -Uri "https://login.windows.net/$tenant/oauth2/token" -Method POST -Body $body ).access_token
$keyCreds = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/applications/$appObjId/keyCredentials" -Method Get -Headers #{"Authorization" = "Bearer $accessToken"}
$keyCreds.value.customKeyIdentifier
Result:
my certs on portal :
query result :
Pls note that make sure your app which you used for getting token with permission below so it can call Microsoft graph API to query your apps :

List Cloud Service Classic use PowerShell and Azure Rest API

I Have a problem. Could you please help me view list Cloud Service Classic use PowerShell and Azure Rest API. When I used script for Web APP I show list Web APP, but when I used scrip for Cloud Service Classic I show error.
# Variables
$TenantId = "" # Enter Tenant Id.
$ClientId = "" # Enter Client Id.
$ClientSecret = "" # Enter Client Secret.
$Resource = "https://management.core.windows.net/"
$SubscriptionId = "" # Enter Subscription Id.
$RequestAccessTokenUri = "https://login.microsoftonline.com/$TenantId/oauth2/token"
$body = "grant_type=client_credentials&client_id=$ClientId&client_secret=$ClientSecret&resource=$Resource"
$Token = Invoke-RestMethod -Method Post -Uri $RequestAccessTokenUri -Body $body -ContentType 'application/x-www-form-urlencoded'
Write-Host "Print Token" -ForegroundColor Green
Write-Output $Token
# Get Azure Resource Groups
$ResourceGroupApiUri = "https://management.core.windows.net/$SubscriptionId/services/hostedservices"
$Headers = #{}
$Headers.Add("Authorization","$($Token.token_type) "+ " " + "$($Token.access_token)")
$ResourceGroups = Invoke-RestMethod -Method Get -Uri $ResourceGroupApiUri -Headers $Headers
Write-Host "Print Resource groups" -ForegroundColor Green
Write-Output $ResourceGroups
Invoke-RestMethod : ForbiddenErrorThe server failed to authenticate the request. Verify that the certificate is valid and
is associated with this subscription.
Actually, there is a built-in ASM PowerShell to list the cloud services associated with the current subscription.
Get-AzureService
Reference - https://learn.microsoft.com/en-us/powershell/module/servicemanagement/azure/get-azureservice?view=azuresmps-4.0.0
Besides, if you insist on calling the ASM rest api with powershell, you could refer to this article, the sample calls the Get Deployment api, just change it to List Cloud Services.
#Request Headers required to invoke the GET DEPLOYMENT REST API
$method
=
“GET”
$headerDate
= ‘2009-10-01’
$headers
= #{“x-ms-version”=“$headerDate“}
#Retrieving the subscription ID
$subID
= (Get-AzureSubscription
-Current).SubscriptionId
$URI
=
https://management.core.windows.net/$subID/services/hostedservices/kaushalz/deployments/4f006bb7d2874dd4895f77a97b7938d0
#Retrieving the certificate from Local Store
$cert
= (Get-ChildItem
Cert:\CurrentUser\My
|
?{$_.Thumbprint -eq
“B4D460D985F1D07A6B9F8BFD67E36BC53A4490FC”}).GetRawCertData()
#converting the raw cert data to BASE64
body
=
“<Binary>—–BEGIN CERTIFICATE—–`n$([convert]::ToBase64String($cert))`n—–END CERTIFICATE—–</Binary>”
#Retrieving the certificate ThumbPrint
$mgmtCertThumb
= (Get-AzureSubscription
-Current).Certificate.Thumbprint
#Passing all the above parameters to Invoke-RestMethod cmdlet
Invoke-RestMethod
-Uri
$URI
-Method
$method
-Headers
$headers
-CertificateThumbprint
” B4D460D985F1D07A6B9F8BFD67E36BC53A4490FC”
-ContentType
$ContentType

Retrieve the host keys from an azure function app

I am trying to script an environment using the Azure cli. I have created a few function apps and would like to add a host key or at least retrieve the default one that is created automatically. The azure cli has no support at all for this.
There seems to be an api (documentation for it seems to be sparse) on the function itself that allows me to get the keys, however you need a key to use it so.. no help there.
https://github.com/Azure/azure-webjobs-sdk-script/wiki/Key-management-API
Eg: https://example-functions.azurewebsites.net/admin/host/keys?code=somecodeyoualreadyknow
I have seen some other examples that use the webapps scm api to download the json file that contains the keys however I'm not sure how to authenticate with this API. I have a service principal (userid, password, tenantid) and I was hoping to not have to add another authentication scheme to my script.
I was just able to make this work with the Azure CLI using this command:
az rest --method post --uri \
"/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Web/sites/$FUNCTION_APP_NAME/host/default/listKeys?api-version=2018-11-01" \
--query functionKeys.default --output tsv
I realize this is a couple years late on the answer, but it might help people who are searching now.
Here are the steps.
Assuming you already have your Kudu deployment credentials. (it sounds like you already know how to do this. You can get it via an ARM call from your service principle, etc)
From kudu deployment creds, you can get a JWT that lets you call the Functions key API.
From the Functions API, you can get all your keys (including your master).
Here's a powershell script that demonstrates the exact calls to go from Kudu deployment creds to Function Master key:
# You need to start with these:
$site = "YourSiteName"
$username='YourDeploymentUserName'
$password='YourDeploymentPassword'
# Now...
$apiBaseUrl = "https://$($site).scm.azurewebsites.net/api"
$siteBaseUrl = "https://$($site).azurewebsites.net"
# For authenticating to Kudu
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
# Call Kudu /api/functions/admin/token to get a JWT that can be used with the Functions Key API
$jwt = Invoke-RestMethod -Uri "$apiBaseUrl/functions/admin/token" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET
# Call Functions Key API to get the master key
$x = Invoke-RestMethod -Uri "$siteBaseUrl/admin/host/systemkeys/_master" -Headers #{Authorization=("Bearer {0}" -f $jwt)} -Method GET
$masterKey = $x.value
I do not know how to get "kudu" credentials with my service principal credentials
If C# code is acceptable, we could use Microsoft.Azure.Management.ResourceManager.Fluent and Microsoft.Azure.Management.Fluent to do that easily. The following is the demo that how to get kudu credentials and run Key management API .I test it locally, it works correctly on my side.
string clientId = "client id";
string secret = "secret key";
string tenant = "tenant id";
var functionName ="functionName";
var webFunctionAppName = "functionApp name";
string resourceGroup = "resource group name";
var credentials = new AzureCredentials(new ServicePrincipalLoginInformation { ClientId = clientId, ClientSecret = secret}, tenant, AzureEnvironment.AzureGlobalCloud);
var azure = Azure
.Configure()
.Authenticate(credentials)
.WithDefaultSubscription();
var webFunctionApp = azure.AppServices.FunctionApps.GetByResourceGroup(resourceGroup, webFunctionAppName);
var ftpUsername = webFunctionApp.GetPublishingProfile().FtpUsername;
var username = ftpUsername.Split('\\').ToList()[1];
var password = webFunctionApp.GetPublishingProfile().FtpPassword;
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
var apiUrl = new Uri($"https://{webFunctionAppName}.scm.azurewebsites.net/api");
var siteUrl = new Uri($"https://{webFunctionAppName}.azurewebsites.net");
string JWT;
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", $"Basic {base64Auth}");
var result = client.GetAsync($"{apiUrl}/functions/admin/token").Result;
JWT = result.Content.ReadAsStringAsync().Result.Trim('"'); //get JWT for call funtion key
}
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + JWT);
var key = client.GetAsync($"{siteUrl}/admin/functions/{functionName}/keys").Result.Content.ReadAsStringAsync().Result;
}
If you just want to get the keys and don't need to automate the authentication process:
Get-AzResource -Name RESOURCE-NAME | Invoke-AzResourceAction -Action host/default/listkeys -Force
Thanks both for your replies. Using your answer Mike S and rummaging around the csharp fluent source code (thanks Tom Sun) I ended up with this. Sure do need a lot of tokens! The credentials I start with are what you would get back from az ad sp create-for-rbac -n $name --role contributor
$credentials = (ConvertFrom-Json $env:AzureCliLogin)
$tenant = $credentials.tenant
$clientId = $credentials.appId
$clientSecret = $credentials.password
$subscriptionId = "<subscription id>"
$body = #{
"grant_type"="client_credentials";
"client_id"=$clientId;
"client_secret"=$clientSecret;
"resource"="https://management.azure.com/"
}
$authInfo = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenant/oauth2/token" -Body $body -Method Post -Headers #{"Content-Type"="application/x-www-form-urlencoded"}
$publishData = Invoke-RestMethod -Uri "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Web/sites/$name/publishxml?api-version=2016-08-01" -Method Post -Headers #{"Authorization"="Bearer $($authInfo.access_token)"}
$userName = $publishData.publishData.publishProfile[0].userName
$password = $publishData.publishData.publishProfile[0].userPWD
$apiBaseUrl = "https://$name.scm.azurewebsites.net/api"
$siteBaseUrl = "https://$name.azurewebsites.net"
# For authenticating to Kudu
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
# Call Kudu /api/functions/admin/token to get a JWT that can be used with the Functions Key API
$jwt = Invoke-RestMethod -Uri "$apiBaseUrl/functions/admin/token" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET
# Call Functions Key API to get the master key
$x = Invoke-RestMethod -Uri "$siteBaseUrl/admin/host/systemkeys/_master" -Headers #{Authorization=("Bearer {0}" -f $jwt)} -Method GET
$masterKey = $x.value
If you want to do this in bash, see this gist for a start
Make sure you have the latest version of the Az Module.
Install:
Install-Module -Name Az -Force
or
Update:
Update-Module -Name Az
Be sure and launch a new PowerShell window after running one of the above commands.
Then you can just run the following after you set up your resource group name and function name variables:
$azureFunction = Get-AzFunctionApp -ResourceGroupName $resourceGroupName -Name $azureFunctionName
$keys = Invoke-AzResourceAction -ResourceId $($azureFunction.Id) -Action "host/default/listKeys" -Force
$defaultKey = $keys.functionKeys.default

Resources