azure-sql-database - 从 Azure Function App 的托管服务标识调用时出现 SQL Azure 模拟错误

标签 azure-sql-database azure-functions

场景

我有一个 Azure Functions 应用程序,当文件添加到 blob 存储时将被触发。每天触发一次。

该应用程序将调用 SQL Azure 数据库中的存储过程,并使用函数应用程序的托管服务标识进行连接。该存储过程具有 WITH EXECUTE AS OWNER 子句,它会将添加的文件批量插入到数据库中。

注意:托管身份的数据库用户已创建并被授予执行相关存储过程的权限。

问题

默认情况下,存储过程调用将失败,并显示错误消息(下面的完整堆栈跟踪):

Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.

如果我使用管理员用户 ID 登录 SQL Management Studio 中的数据库并简单地执行 EXECUTE AS USER = '...' 语句,然后很快重新触发 Functions App,来自 Functions 应用程序的下一个存储过程调用将成功。

似乎我需要手动“刷新”数据库中的某些内容,以允许来自 Functions App 的存储过程调用能够成功模拟。

注意:托管服务标识通常在调用数据库时起作用。似乎只是数据库用户模拟有问题。

问题

如果我想使用托管服务身份调用存储过程,我该如何解决这个问题?

异常堆栈跟踪

Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: OnFileAddedToInbox
 ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at Microsoft.Data.SqlClient.SqlCommand.CompleteAsyncExecuteReader(Boolean isInternal, Boolean forDescribeParameterEncryption)
   at Microsoft.Data.SqlClient.SqlCommand.InternalEndExecuteNonQuery(IAsyncResult asyncResult, Boolean isInternal, String endMethod)
   at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult)
   at Microsoft.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at AzureFunc.OnFileAddedToInbox.Run(CloudBlockBlob blob, String fileName, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.Azure.WebJobs.Host.Executors.VoidTaskMethodInvoker`2.InvokeAsync(TReflected instance, Object[] arguments) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\VoidTaskMethodInvoker.cs:line 20
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync(Object instance, Object[] arguments) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 52
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker, ParameterHelper parameterHelper, CancellationTokenSource timeoutTokenSource, CancellationTokenSource functionCancellationTokenSource, Boolean throwOnTimeout, TimeSpan timerInterval, IFunctionInstance instance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 585
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstanceEx instance, ParameterHelper parameterHelper, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 532
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, ParameterHelper parameterHelper, IFunctionOutputDefinition outputDefinition, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 468
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 278
ClientConnectionId:712b8ea4-c8e9-4701-aed1-643b16b111d9
Error Number:15517,State:1,Class:16
ClientConnectionId before routing:d9545837-a804-4a42-8e84-12d5edac5f17
Routing Destination:***.database.windows.net,11069
   --- End of inner exception stack trace ---
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 322
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 117

最佳答案

这里的问题是 Managed Identity needs to have a user created with same name to access the Database通过 SQL 脚本。

尝试运行

CREATE USER [<identity-name>] FROM EXTERNAL PROVIDER;

并授予用户适当的访问权限。

一个没有很好记录的调用是,如果您的 Azure 函数被删除并重新创建,则脚本将需要再次运行,因为它将具有不同的指纹。 Azure SQL 数据库是为数不多的需要像这样为托管身份重新分配访问权限的资源之一。

关于azure-sql-database - 从 Azure Function App 的托管服务标识调用时出现 SQL Azure 模拟错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60160941/

相关文章:

sql - 检查子查询中是否存在记录

sql-server - Azure SQL Server - 如何授予用户对主数据库的只读访问权限

node.js - 如何使用 azure 函数处理流数据?

azure-sql-database - 天蓝色故障转移组的连接字符串

Azure Portal添加可以创建Web应用程序,sql服务器和其他资源的用户

Azure Sql 数据库只读

Node.js typescript Azure 函数 : Cannot import with absolute path ( minimal reproducible example attached)

c# - Azure Function App 如何与 Azure 资源交互?

azure - 从 VS Code 部署 Azure 函数 - 成功但在门户中不可见

azure - 函数未使用 ARM 模板在 Azure 函数应用程序内创建