У меня есть функция Azure (HTTP-триггер), которая записывает данные в очередь, а также в таблицу хранения. Он работал нормально, но теперь мне нужно переместить все, чтобы использовать управляемые удостоверения.
Я смог изменить триггер HTTP, чтобы использовать переменную env __serviceUri для подключения вместо использования строки подключения. Но теперь мне нужно выяснить, как обновить мою логику, которая записывает в таблицу хранилища.
Вот соответствующий код.
HTTP-триггер
[FunctionName("Createwidget")]
public async Task<IActionResult> Createwidget(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "toys/widgets")] HttpRequest req,
[Queue("widgets"), StorageAccount("ExtStorageQueue")] ICollector<string> messageQueue,
ILogger log)
{
widgetResponse response = new widgetResponse();
var content = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation($"Received following payload: {content}");
var widgetRequest = JsonConvert.DeserializeObject<widget>(content);
if (widgetRequest.name != null){
messageQueue.Add(JsonConvert.SerializeObject(widgetRequest));
// this is where I need to update the code
response = await storage.ProvisioningRequest(widgetRequest, req.HttpContext.Items["MS_AzureFunctionsRequestID"].ToString(), "enqueued");
}
else {
response.status = "Error: Invalid Request";
response.requestId=null;
}
return new OkObjectResult(JsonConvert.SerializeObject(response));
}
Это фрагмент из storage.ProvisioningRequest().
GetStorageAccountConnectionData
var serviceClient = new TableServiceClient(
new Uri(connection.storageUri),
new TableSharedKeyCredential(connection.storageAccountName, connection.storageAccountKey));
var tableClient = serviceClient.GetTableClient(connection.tableName);
await tableClient.CreateIfNotExistsAsync();
Вот как я создаю соединение:
private void GetStorageAccountManagedIDConnection()
{
var azureWebJobsStorage = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
String[] accountDetailsArray = azureWebJobsStorage.Split(";");
String[] accountNameArray = accountDetailsArray[1].Split(" = ");
connection.storageAccountName = accountNameArray[1];
var storageAccount= Environment.GetEnvironmentVariable("ExtStorageQueue");
String[] storageAccountDetailsArray = storageAccount.Split(";");
String[] accountKeyDetailsArray = storageAccountDetailsArray[2].Split("AccountKey = ");
string storageKey = accountKeyDetailsArray[1];
connection.tableName = Environment.GetEnvironmentVariable("squeueTable");
connection.storageUri = $"https://{connection.storageAccountName}.table.core.windows.net/{connection.tableName}";
connection.storageAccountKey = storageKey;
}
Вот как выглядит мой файл local.settings.json:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=mystorageAccountName;EndpointSuffix=core.windows.net;AccountKey=supersecretKey/asdf+asdf= = ",
"squeueTable": "provisionedWidgets",
"ExtStorageQueue__serviceUri": "https://mystorageAccountName.queue.core.windows.net",
},
"ConnectionStrings": {}
}
Есть ли способ сделать это? Я читаю https://docs.microsoft.com/en-us/dotnet/api/azure.data.tables.tableclient?view=azure-dotnet#constructors и не вижу никаких конструкторов, которые позволяют мне использовать управляемый идентификатор.
Любая помощь будет оценена
РЕДАКТИРОВАТЬ 1
Вот упрощенный метод, который создает данные конфигурации подключения:
private void GetStorageAccountConnectionData()
{
//TODO: remove hardcoded values and extract from local.settings.json instead. For testing purposes only to see how serivceUri works.
connection.storageAccountName = "mystorageaccountname";
connection.tableName = Environment.GetEnvironmentVariable("StorageTableName");
connection.storageTableUri = $"https://{connection.storageAccountName}.table.core.windows.net/{connection.tableName}";
connection.storageQueueUri = $"https://{connection.storageAccountName}.queue.core.windows.net/";
}
и это логика, которая его потребляет:
GetStorageAccountConnectionData();
var serviceClient = new TableServiceClient(new Uri(connection.storageTableUri), new DefaultAzureCredential());
var tableClient = serviceClient.GetTableClient(connection.tableName);
TableEntity origEntity = tableClient.GetEntity<TableEntity>(
ENQUEUED_PARTITION,
notification.requestId);
Ошибок компиляции нет, но таблица хранилища не записывается.
В настоящее время я пытаюсь узнать о создании сообщений/журналов отладки, так как я не могу заставить свою локальную среду отладки работать.
РЕДАКТИРОВАТЬ 2
Наконец-то я настроил свою локальную среду, чтобы я мог отлаживать. Таким образом, логика, которая записывает в мою очередь хранилища, работает, но когда я пытаюсь записать в таблицу хранения, я теперь вижу, в чем заключается полная ошибка. Это ошибка:
Failed to create storage record:Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. ure.
RequestId:asdf-0002-asdf-6574-asdf
Time:2022-05-10T13:45:24.6319496Z
Status: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)
ErrorCode: AuthenticationFailed
Content:
{"odata.error":{"code":"AuthenticationFailed","message":{"lang":"en-US","value":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including
is formed correctly including the signature.\nRequestId:9f775fd8-0002-002c-6574-648209000000\nTime:2022-05-10T13:45:24.6319496Z"}}}
Headers:
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: asdf-asdf-asdf-asdf
x-ms-error-code: REDACTED
Date: Tue, 10 May 2022 13:45:23 GMT
Content-Length: 299
Content-Type: application/json
Также, чтобы быть явным, такое же поведение происходит и при тестировании в облаке. Поэтому независимо от того, звоню ли я
POST https://myfunctionapp.azurewebsites.net/widgets/workspaces
или
POST http://localhost:7071/widgets/workspaces
это то же самое поведение. Очередь хранилища обновляется, но не таблица.
Что касается управляемого идентификатора, теперь он имеет следующие разрешения:
@GauravMantri. Прохладно! Я проверю это
вы пытаетесь создать таблицу или получить доступ к таблице? для чтения/записи в таблицу нужны разные разрешения: Storage Table Data Contributor
или Storage Table Data Reader
.
оба. но у меня есть роль участника данных таблицы хранения в группе ресурсов для управляемого идентификатора. У меня также есть роль участника данных очереди хранения в группе ресурсов ... и, похоже, она работает. Я только что добавил также на уровень учетной записи хранения. но ти не работает.
@Thomas, пожалуйста, смотрите редактирование 2
распространение заданий может занять несколько минут, и вам, вероятно, также потребуется выйти из системы / снова войти в систему
Также вы говорите здесь о локальной аутентификации или использовании управляемого удостоверения, я запутался.
@ Томас, нет проблем. Основной вопрос о том, как писать в таблицу хранилища. Предоставленный вами ответ не работает для меня, но поскольку я не могу отлаживать локально, я не могу предоставить вам полезную информацию о том, почему/что не удается. Все, что я вижу, это то, что таблица НЕ заполняется вверх по течению. У меня есть отдельный вопрос о том, как пройти аутентификацию через vscode.
Давайте продолжить обсуждение в чате.
@Thomas, у меня работает локальная отладка. См. Изменить 2 сейчас, чтобы узнать о полной ошибке, когда я пытаюсь записать в учетную запись хранения, используя ваш пример кода. Пожалуйста и спасибо!
Удалось ли вам заставить письмо работать?
Вам нужно добавить ссылку на эти пакеты:
Вашему функциональному приложению потребуется роль Storage Account Contributor
или Contributor
на уровне хранилища (если честно, не уверен).
Вот фрагмент того, как может выглядеть ваш код:
var serviceClient = new TableServiceClient(
new Uri(connection.storageUri), new DefaultAzureCredential());
var tableClient = serviceClient.GetTableClient (connection.tableName);
await tableClient.CreateIfNotExistsAsync();
k постараюсь протестировать в ближайшее время. Когда я переключаюсь на использование управляемых идентификаторов, локально ничего не работает, поэтому сначала нужно выяснить это, прежде чем я смогу это проверить. Я опубликую снова в ближайшее время. Спасибо.
Вы используете vs code/visual studio? вы можете войти в свою учетную запись в обоих случаях и заставить ее работать локально
Я использую vscode. вот все подробности, если поможет: stackoverflow.com/questions/72142747/…
Fwiw я также попытался упростить логику подключения, просто чтобы использовать жестко запрограммированные значения, потому что я не могу ничего отлаживать локально ... когда я публикую fn вверх по течению, очередь записывается с использованием управляемого идентификатора, но таблица не работает. У меня нет никаких полезных ошибок, хотя. В любом случае я попытаюсь обновить вопрос здесь с изменениями кода, чтобы информация была по крайней мере полной.
пожалуйста, см. Редактировать 1 для последнего кода.
пометка как ответ, потому что я думаю, что основная причина проблемы не связана с логикой подключения. Теперь это проблема с разрешениями. Единственное, что мне нужно было сделать, чтобы этот ответ заработал, — добавить мои AZURE_TENANT_ID, AZURE_CLIENT_ID и AZURE_CLIENT_SECRET в файл local.settings.json. Затем я смог подключиться к учетной записи хранения.
Как насчет этого: docs.microsoft.com/en-us/dotnet/api/…?