Получить ключи хоста из приложения-функции Azure
Я пытаюсь написать сценарий среды, используя клиент Azure. Я создал несколько функциональных приложений и хотел бы добавить ключ хоста или, по крайней мере, получить ключ по умолчанию, который создается автоматически. Лазурный Cli не имеет никакой поддержки для этого.
Похоже, что на самой функции есть API (документация на нее немногочисленна), которая позволяет мне получить ключи, однако вам нужен ключ, чтобы использовать его, так что... никакой помощи нет.
https://github.com/Azure/azure-webjobs-sdk-script/wiki/Key-management-API
Например: https://example-functions.azurewebsites.net/admin/host/keys?code=somecodeyoualreadyknow
Я видел несколько других примеров, которые используют scm api webapps для загрузки файла json, содержащего ключи, однако я не уверен, как проходить аутентификацию с помощью этого API. У меня есть принципал службы (ИД пользователя, пароль, tenantid), и я надеялся, что мне не придется добавлять другую схему аутентификации в мой скрипт.
7 ответов
Вот шаги.
- Предполагая, что у вас уже есть учетные данные для развертывания Kudu. (Похоже, вы уже знаете, как это сделать. Вы можете получить его с помощью вызова ARM из принципа обслуживания и т. д.)
- Из кредитов развертывания kudu вы можете получить JWT, который позволяет вам вызывать API-интерфейс ключа функций.
- Из API функций вы можете получить все свои ключи (включая своего мастера).
Вот сценарий PowerShell, который демонстрирует точные вызовы, которые нужно перейти от кредитов развертывания Kudu к ключу Function Master:
# 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
Я просто смог выполнить эту работу с помощью Azure CLI с помощью этой команды:
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
Я понимаю, что ответ пришел с опозданием на пару лет, но это может помочь людям, которые ищут сейчас.
Я не знаю, как получить учетные данные "kudu" с учетными данными участника моей службы
Если код C# приемлем, мы могли бы использовать https://www.nuget.org/packages/Microsoft.Azure.Management.ResourceManager.Fluent/ и https://www.nuget.org/packages/Microsoft.Azure.Management.Fluent/, чтобы сделать это легко. Ниже приведена демонстрация того, как получить учетные данные kudu и запустить API управления ключами. Я проверяю его локально, он корректно работает на моей стороне.
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;
}
Если вы просто хотите получить ключи и вам не нужно автоматизировать процесс аутентификации:
Get-AzResource -Name RESOURCE-NAME | Invoke-AzResourceAction -Action host/default/listkeys -Force
Если вы хотите сделать это в Bash, посмотрите эту суть для начала
Спасибо обоим за ваши ответы. Используя ваш ответ Mike S и покопавшись в беглом исходном коде csharp (спасибо Tom Sun), я закончил с этим. Конечно, нужно много токенов! Учетные данные, с которых я начинаю, - это то, что вы получите от 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
Убедитесь, что у вас установлена последняя версия модуля Az.
Установить:
Install-Module -Name Az -Force
или же
Обновлять:
Update-Module -Name Az
Обязательно запустите новое окно PowerShell после выполнения одной из приведенных выше команд.
Затем вы можете просто запустить следующее после установки переменных имени группы ресурсов и имени функции:
$azureFunction = Get-AzFunctionApp -ResourceGroupName $resourceGroupName -Name $azureFunctionName
$keys = Invoke-AzResourceAction -ResourceId $($azureFunction.Id) -Action "host/default/listKeys" -Force
$defaultKey = $keys.functionKeys.default