Azure Function Key Management API - Authentication error - azure

I have two Azure function apps, both in the same Azure subscription. I can retrieve keys for one but not for the other. As far as I can see there is no difference between the two function apps.
I'm using this Powershell code:
function GetHostKey
{
param($webAppName, $resourceGroupName)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Write-Host "Getting master key from $webAppName"
$xml = [xml](Get-AzureRmWebAppPublishingProfile -Name $webAppName -ResourceGroupName $resourceGroupName -Format WebDeploy -OutputFile null)
$msdeployUsername = $xml.SelectNodes("//publishProfile[#publishMethod=`"MSDeploy`"]/#userName").value
$msdeployPassword = $xml.SelectNodes("//publishProfile[#publishMethod=`"MSDeploy`"]/#userPWD").value
$apiBaseUrl = "https://$webAppName.scm.azurewebsites.net/api"
$siteBaseUrl = "https://$webAppName.azurewebsites.net"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $msdeployUsername,$msdeployPassword)))
$jwt = Invoke-RestMethod -Uri "$apiBaseUrl/functions/admin/token" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method GET
$uri = "$siteBaseUrl/admin/host/systemkeys/_master"
$response = Invoke-RestMethod -Uri $uri -Headers #{Authorization=("Bearer {0}" -f $jwt)} -Method GET
return $response.value
}
The call to $siteBaseUrl/admin/host/systemkeys/_master returns the expected json for one function app, but the other one returns a login screen.

Compare both functions settings, versions. Try to get the keys manually from the portal to isolate the source of the problem. I had the same problem till i deleted and recreated the functions.

Related

Export all API names Azure APIM

I am trying to export all the url endpoints of my APIs which are stored in Azure APIM.
I need them listed in the format [POST]: https://apim-resource-name.azure-api.net/api-name/api-function, or something similar, so I am trying to enumerate all the endpoints first and the VERB that can be used much like what SwaggerUI or one of the OpenAPI docs might show.
I have this code so far but cannot get the output I would like, am I on the right track or is there any easier way to do this even via UI? I have also tried exporting the template and parsing the script, but it seemed overly complicated for this task.
#az login
$token = az account get-access-token | ConvertFrom-Json
$token = $token.accessToken -replace "`n","" -replace "`r",""
$headers = #{Authorization="Bearer $token.accessToken"}
$subscriptionId = 'subscriptionid'
$resourceGroupName = 'resourcegroupname'
$resourceName = 'resourcename'
$apiName = 'apiname'
$url_getapiexport = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$resourceName/apis/$apiName`?format=swagger-link&export=true&api-version=2021-08-01" #GET
$url_getapiexport
#Invoke-RestMethod -Uri $url_getapiexport -Method GET -Headers #{Authorization="Bearer $token"} -ContentType "application/json"
$url_getapibytags = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$resourceName/apisByTags?&includeNotTaggedApis=true&api-version=2021-08-01" #GET
$url_getapibytags
$api_tags = Invoke-RestMethod -Uri $url_getapibytags -Method GET -Headers #{Authorization="Bearer $token"} -ContentType "application/json"
$api_tags
foreach ($api in $api_tags) {
write-host API: $api.value.api.name
}
So if you want to export all APIM APIs and their service URLs you can do like this (replace xxx with correct values). Example in PHP
<?php
echo "[INFO] API Names and Service Urls \n\n";
$apiList = shell_exec('az apim api list --resource-group "xxx" --service-name "xxx" ');
$apis = json_decode($apiList, true);
$cli = "az rest --method get --url";
foreach ($apis as $api)
{
$name = $api["name"];
$apiRequest = "$cli " . "\"https://management.azure.com/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.ApiManagement/service/xxx/apis/$name?api-version=2021-08-01\"";
$json = shell_exec($apiRequest);
$apiInfo = json_decode($json, true);
$displayName = $apiInfo["properties"]["displayName"];
$serviceUrl = $apiInfo["properties"]["serviceUrl"];
printf("%s: %s \n", $displayName, $serviceUrl);
}
?>

In azure can we update the profile.ps1 file function app?

We have a function in azure portal. When we create function app, we can see the profile.ps1 in App Files section of a function App. Can we edit this profile.ps1 file using PowerShell or CLI commands. If Yes, please help me out.
Any help can be appriciated...!
In this case, your option is to use Kudu API via powershell to update the profile.ps1, in my sample, I store the new profile.ps1 with the path C:\Users\Administrator\Desktop\profile.ps1 in local, it works fine on my side.
Sample:
$appsvWebAppName = "<functionapp-name>"
$resourceGroupName = "<group-name>"
$resource = Invoke-AzResourceAction -ResourceGroupName $resourceGroupName -ResourceType Microsoft.Web/sites/config -ResourceName "$appsvWebAppName/publishingcredentials" -Action list -ApiVersion 2018-02-01 -Force
$username = $resource.Properties.publishingUserName
$password = $resource.Properties.publishingPassword
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
$userAgent = "powershell/1.0"
$apiUrl = "https://$appsvWebAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/profile.ps1"
$filePath = "C:\Users\Administrator\Desktop\profile.ps1"
$headers = #{
'Authorization' = 'Basic ' + $base64AuthInfo
'If-Match' = '*'
}
Invoke-RestMethod -Uri $apiUrl -Headers $headers -UserAgent $userAgent -Method PUT -InFile $filePath -ContentType "multipart/form-data"
Check in the portal:

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

After zip deloy, azure app service dont have any function

I created C# Azure Timmer function, then I published the App using GUI publish on Visual Studio, everything worked. Then I change to use Powershell script:
$username = $creds.Properties.PublishingUserName
$password = $creds.Properties.PublishingPassword
$apiUrl = "https://" + $FuncAppName + ".scm.azurewebsites.net/api/zipdeploy"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
$filePath = "publish.zip"
$userAgent = "powershell/1.0"
Invoke-RestMethod -Uri $apiUrl -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -UserAgent $userAgent -Method POST -InFile $filePath -ContentType "multipart/form-data"
Don't get any error, but when I check on Azure, my Service app doesn't have my new function. So how to fix it?
The apiUrl should point to the wwwroot folder, for zipDeploy
$apiUrl = "https://" + $functionAppName + ".scm.azurewebsites.net/api/zip/site/wwwroot"
This is what i've been using and it works fine.

Function Level Authorization Authorize keys in Azure can we manage these keys through CICD

Can we managae keys through CICD?
Means i need to manage these through CICD not portal or Rest Srevice is it possible?
everything is being managed through rest api (ultimately) so this ask makes very little sense. you can manage those only using the rest calls (as far as I know).
function Add-AzureFunctionKey {
Param(
[string]$appName,
[string]$resourceGroup,
[string]$funcKeyName,
[string]$funcKeyValue
)
$AzureContext = Get-AzureRmContext
if(!$AzureContext){
Write-Output "Please login to your Azure Account"
Login-AzureRmAccount
}
$SubscriptionId = (Get-AzureRmSubscription | select Name, State, SubscriptionId, TenantId | Out-GridView -Title "Azure Subscription Selector" -PassThru).SubscriptionId
Get-AzureRmSubscription -SubscriptionId $SubscriptionId | Select-AzureRmSubscription
$PublishingProfile = (Get-AzureRmWebAppPublishingProfile -ResourceGroupName $resourceGroup -Name $appName)
$user = (Select-Xml -Xml $PublishingProfile -XPath "//publishData/publishProfile[contains(#profileName,'Web Deploy')]/#userName").Node.Value
$pass = (Select-Xml -Xml $PublishingProfile -XPath "//publishData/publishProfile[contains(#profileName,'Web Deploy')]/#userPWD").Node.Value
$pair = "$($user):$($pass)"
$kuduCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$authToken = Invoke-RestMethod -Uri "https://$appName.scm.azurewebsites.net/api/functions/admin/token" -Headers #{Authorization = ("Basic {0}" -f $kuduCredentials)} -Method GET
$Functions = Invoke-RestMethod -Method GET -Headers #{Authorization = ("Bearer {0}" -f $authToken)} -Uri "https://$appName.azurewebsites.net/admin/functions"
$Functions = $Functions.Name
ForEach ($functionName in $Functions) {
$data = #{
"name" = "$funcKeyName"
"value" = "$funcKeyValue"
}
$json = $data | ConvertTo-Json;
$keys = Invoke-RestMethod -Method PUT -Headers #{Authorization = ("Bearer {0}" -f $authToken)} -ContentType "application/json" -Uri "https://$appName.azurewebsites.net/admin/functions/$functionName/keys/$funcKeyName" -body $json
Write-Output "Function $FunctionName Key updated $keys"
}
}
here's a sample found online, i didnt test it. there are a few examples online more or less like the one above.
Source: https://www.powershellbros.com/add-azure-function-key/

Resources