【问题标题】:how to connect Azure SQL DW using Managed Identity using azure function如何使用 azure 函数使用托管标识连接 Azure SQL DW
【发布时间】:2021-08-15 22:15:38
【问题描述】:

我已尝试使用 Azure 函数代码连接到 SQL Server,并且能够成功连接。但是,当我尝试对 SQL DW(专用 SQL 池)使用相同的代码时,出现以下错误。

谁能帮我解决这个问题?我无法弄清楚这里有什么问题。

message": "Exception while executing function: Synapse_Connectivity -> A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 25 - Connection string is not valid) -> The parameter is incorrect",
    "errorDetails": "Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: Synapse_Connectivity ---> System.Data.SqlClient.SqlException : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 25 - Connection string is not valid) ---> System.ComponentModel.Win32Exception : The parameter is incorrect \r\n   End of inner exception\r\n   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity,SqlConnectionString connectionOptions,SqlCredential credential,Object providerInfo,String newPassword,SecureString newSecurePassword,Boolean redirectedUserInstance,SqlConnectionString userConnectionOptions,SessionData reconnectSessionData,DbConnectionPool pool,String accessToken,Boolean applyTransientFaultHandling,SqlAuthenticationProviderManager sqlAuthProviderManager)\r\n   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options,DbConnectionPoolKey poolKey,Object poolGroupProviderInfo,DbConnectionPool pool,DbConnection owningConnection,DbConnectionOptions userOptions)\r\n   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool,DbConnection owningObject,DbConnectionOptions options,DbConnectionPoolKey poolKey,DbConnectionOptions userOptions)\r\n   at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject,DbConnectionOptions userOptions,DbConnectionInternal oldConnection)\r\n   at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject,DbConnectionOptions userOptions,DbConnectionInternal oldConnection)\r\n   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,UInt32 waitForMultipleObjectsTimeout,Boolean allowCreate,Boolean onlyOneCheckConnection,DbConnectionOptions userOptions,DbConnectionInternal& connection)\r\n   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject,TaskCompletionSource`1 retry,DbConnectionOptions userOptions,DbConnectionInternal& connection)\r\n   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection,TaskCompletionSource`1 retry,DbConnectionOptions userOptions,DbConnectionInternal oldConnection,DbConnectionInternal& connection)\r\n   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection,DbConnectionFactory connectionFactory,TaskCompletionSource`1 retry,DbConnectionOptions userOptions)\r\n   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection,DbConnectionFactory connectionFactory,TaskCompletionSource`1 retry,DbConnectionOptions userOptions)\r\n   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)\r\n   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)\r\n   at System.Data.SqlClient.SqlConnection.Open()\r\n   at async FunctionApp_WBA_QA.Synapse_Connectivity.Run(HttpRequestMessage req,TraceWriter log)\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync[TReflected,TReturnValue](Object instance,Object[] arguments)\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker,ParameterHelper parameterHelper,CancellationTokenSource timeoutTokenSource,CancellationTokenSource functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan timerInterval,IFunctionInstance instance)\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstance instance,ParameterHelper parameterHelper,TraceWriter traceWriter,CancellationTokenSource functionCancellationTokenSource)\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??) \r\n   End of inner exception\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)\r\n   at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance functionInstance,CancellationToken cancellationToken)\r\n   at Microsoft.Azure.WebJobs.Host.Executors.ExceptionDispatchInfoDelayedException.Throw()\r\n   at async Microsoft.Azure.WebJobs.JobHost.CallAsync(??)\r\n   at async Microsoft.Azure.WebJobs.Script.ScriptHost.CallAsync(String method,Dictionary`2 arguments,CancellationToken cancellationToken)\r\n   at async Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.HandleRequestAsync(FunctionDescriptor function,HttpRequestMessage request,CancellationToken cancellationToken)\r\n   at async Microsoft.Azure.WebJobs.Script.Host.FunctionRequestInvoker.ProcessRequestAsync(HttpRequestMessage request,CancellationToken cancellationToken,WebScriptHostManager scriptHostManager,WebHookReceiverManager webHookReceiverManager)\r\n   at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.<>c__DisplayClass3_0.<ExecuteAsync>b__0(??)\r\n   at async Microsoft.Azure.WebJobs.Extensions.Http.HttpRequestManager.ProcessRequestAsync(HttpRequestMessage request,Func`3 processRequestHandler,CancellationToken cancellationToken)\r\n   at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.ExecuteAsync(HttpControllerContext controllerContext,CancellationToken cancellationToken)\r\n   at async System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n   at async System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n   at async Microsoft.Azure.WebJobs.Script.WebHost.Handlers.WebScriptHostHandler.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n   at async Microsoft.Azure.WebJobs.Script.WebHost.Handlers.SystemTraceHandler.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n   at async System.Web.Http.HttpServer.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)"
}

我的配置是:

“CFG_SQLDB_server”:“XXXX.database.windows.net”,
"CFG_SQLDB_database": "XXXXqadb",
"SYNAPSE_SQL_server": "XXXXsqlsrv.database.windows.net",
"SYNAPSE_SQL_database": "XXXXqa-sqldw"

using System;
using System.Data.SqlClient;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;

namespace FunctionApp_SQL
{
    public static class Synapse_Connectivity
    {
        [FunctionName("Synapse_Connectivity")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function processed a request.");

            string synapse_db_server = GetEnvironmentVariable("SYNAPSE_SQLDB_server");
            string synapse_db_name = GetEnvironmentVariable("SYNAPSE_SQLDB_database");

            string ResourceId = "https://database.windows.net/";

            string sqlConnectionString = String.Format("Data Source=tcp:{0},1433;Initial Catalog={1};Persist Security Info=False;Connect Timeout=30;Encrypt=True;TrustServerCertificate=False;MultipleActiveResultSets=true", synapse_db_server, synapse_db_name);

            log.Info($"sqlConnectionString : {sqlConnectionString}");

            /*Gettting the Token FOR SQL*/
            var tokenProvider = new AzureServiceTokenProvider();
            string accessToken = await tokenProvider.GetAccessTokenAsync(ResourceId);
            log.Info($"AccessToken : {accessToken}");

            log.Info("Connecting to database.");

            var myObj = "";

            using (SqlConnection conn = new SqlConnection(sqlConnectionString))
            {
                conn.AccessToken = accessToken;
                conn.Open();

                var statement = $"select * from ext.test for json path";
                log.Info($"{statement}");

                using (SqlCommand cmd = new SqlCommand(statement, conn))
                {
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            log.Info($"{reader.GetString(0)}");
                            myObj = reader.GetString(0);

                        }
                    }
                }
            }

            var jsonToReturn = JsonConvert.SerializeObject(myObj);

            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(jsonToReturn, Encoding.UTF8, "application/json")
            };

        }

        public static string GetEnvironmentVariable(string name)
        {
            return System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
        }
    }
}

【问题讨论】:

    标签: c# azure azure-functions azure-sqldw azure-managed-identity


    【解决方案1】:

    根据您的帖子,我假设这是一个“专用 SQL 池(以前称为 SQL DW)”而不是 Synapse 专用 SQL 池,它会有一些不同的答案。

    我不保证这一切都会奏效,但我想到了一些项目。

    1. 确保 SQL Server 防火墙配置为允许 Azure 服务:

    1. 在 SQL Server IAM 中,您可能需要将 Reader RBAC 角色授予 Azure Function 的托管标识:

    [注意:此示例具有 SQL 安全管理器,您的角色很可能是读者]

    1. 我认为您需要将 USER ... FROM EXTERNAL PROVIDER 添加到 Azure 函数的数据库并授予它 db_datareader 权限:

      从外部提供商创建用户 [your_azure_function]; EXEC sp_addrolemember 'db-datareader' [your_azure_function];

    This article 用于连接不同的服务,但我认为一般规则可能适用。

    【讨论】:

    • 谢谢乔尔,是的,你是对的。我正在寻找专用 SQL 池(以前称为 SQL DW)。我已按照上述所有步骤操作,但仍然出现错误。因此,我对这种方法有点怀疑。特别是当我按照相同的步骤访问数据库并成功时。
    • 我不知道还能告诉你什么,但运行时连接字符串似乎有问题。
    猜你喜欢
    • 2022-12-19
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 2020-05-02
    相关资源
    最近更新 更多