【问题标题】:Configure NLog to write log to Azure SQL server with manage Identity token配置 NLog 以使用管理标识令牌将日志写入 Azure SQL 服务器
【发布时间】:2019-08-20 18:02:16
【问题描述】:

我正在使用 NLog 并使用 ADO.NET 提供程序将日志消息写入数据库。

我已为我的服务器启用托管标识,我想连接托管标识并在 Azure SQL 中写入日志。我在 nlog 配置文件中有 SP。

我怎样才能做到这一点? nlog配置文件需要修改什么?

  • NLog 版本:4.6.6
  • 平台:. .NET Core 2
  • 需要使用 Azure SQL 中的托管标识记录错误

编辑- 此外,我尝试通过代码构建数据库目标。但无法设置访问令牌。 它正在抛出错误

不支持关键字:',access_token'。

LogManager.LoadConfiguration(String.Concat(Directory.GetCurrentDirectory(), "/nlog.config"));
string connectionString = "Data Source=servername.database.windows.net; Initial Catalog=dbname;";
SqlConnection conn = new SqlConnection(connectionString);
conn.AccessToken = accessToken;
conn.Open();
var databaseTarget = (DatabaseTarget)LogManager.Configuration.FindTargetByName("database");
databaseTarget.ConnectionString = string.Format("{0},access_token ={1}", connectionString, conn.AccessToken); 

【问题讨论】:

  • 您是否尝试过使用想要的身份设置连接字符串:docs.microsoft.com/en-us/azure/storage/common/…
  • 我正在使用 Azure sql 存储日志,而 nlog 文档在其文档中没有任何参数化身份令牌的内容。 github.com/NLog/NLog/wiki/Database-target
  • NLog DatabaseTarget 要求您使用 ConnectionString 来设置身份验证。您是否尝试过询问 Microsoft Azure SQL 是否可以与 Ado-ConnectionString 一起使用?
  • 嗨 Rolf,我可以使用 System.Data.SqlClient 的 SqlConnection 连接 Azure Sql。 SqlConnection 支持 access_token 属性。我在 NLog.Targets 的 DatabaseTarget 类中找不到类似的东西。我正在使用 4.6.6 的 NLog 类。
  • NLog DatabaseTarget 不是 Azure SQL 特定的。所以不能直接设置SqlConnection.acces_token,除非可以使用ConnectionString。

标签: c# azure-active-directory azure-sql-database nlog azure-virtual-machine


【解决方案1】:

NLog 4.7 现已发布,支持分配 DbConnection 属性,如 AccessToken。可以使用这个 nuget-package 获取 AccessToken:

https://www.nuget.org/packages/NLog.Extensions.AzureAccessToken/

<extensions>
  <add assembly="NLog.Extensions.AzureAccessToken" /> 
</extensions>

<targets>
  <target xsi:type="Database" connectionString="...">
    <dbProvider>Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient</dbProvider>
    <connectionProperty name="AccessToken" layout="${AzureAccessToken:ResourceName=${gdc:DatabaseHostSuffix}}"  />
  </target>
</targets>

然后你可以像这样初始化它:

NLog.GlobalDiagnosticsContext.Set("DatabaseHostSuffix", $"https://{DatabaseHostSuffix}/");
NLog.LogManager.LoadConfiguration("nlog.config");

更新 Microsoft.Data.SqlClient 2.1.0(及更高版本)支持 ConnectionString 中的 Authentication-选项,可启用内置 AD 身份验证。这消除了使用 NLog.Extensions.AzureAccessToken 的需要。

将身份验证分配给 Active Directory 默认的示例:

string ConnectionString = @"Server=demo.database.windows.net; Authentication=Active Directory 默认值;Database=testdb;";

另见:Using Active Directory Default authentication

【讨论】:

  • 我欠你一杯啤酒。
【解决方案2】:

基于NLog official target reference 和 Rolf 指出的。 NLog 不提供使用访问令牌连接到 Azure SQL DB 目标的现成接口。所以恐怕你应该在这里使用带有身份验证信息的 Azure SQL 连接字符串。

如果您想避免泄露带有身份验证信息的 Azure SQL 服务器连接字符串,或者您想确保只有带有 MSI 的服务器可以使用 NLog 将日志写入 Azure SQL DB,也许这将是一种解决方法:

storing your Azure SQL server connection string in Azure key-Vault 并配置访问策略以确保只有您的服务器可以访问它。虽然 Nlog 需要连接到 Azure SQL ,但使用服务器 MSI 直接从密钥保管库读取完整的连接字符串以提供 Nlog 目标。

【讨论】:

  • 嗨,如果对我的解决方法有任何不清楚的地方,请随时告诉我:)
【解决方案3】:

您可以创建自己的 Ado-IDbConnection,它包装了一个 SqlConnection,它会在名为 MyAssembly 的项目中自动分配 AccessToken:

namespace MyNameSpace
{
   public class MyDbConnection : System.Data.IDbConnection
   {
      private readonly System.Data.IDbConnection _sqlConnection;

      public MyDbConnection()
      {
          var sqlConnection = new SqlConnection;
          // Could probably delay the assignment to when Open() is called
          sqlConnection.AccessToken = "Hello World";
          _sqlConnection = sqlConnection;
      }

      public string ConnectionString
      {
          get => _sqlConnection.ConnectionString;
          set => _sqlConnection.ConnectionString = value;
      }

      public int ConnectionTimeout => _sqlConnection.ConnectionTimeout;
      public string Database => _sqlConnection.Database;
      public ConnectionState State => _sqlConnection.State;
      public IDbTransaction BeginTransaction() => _sqlConnection.BeginTransaction();
      public IDbTransaction BeginTransaction(IsolationLevel il) => _sqlConnection.BeginTransaction(il);
      public void ChangeDatabase(string databaseName) => _sqlConnection.ChangeDatabase(databaseName);
      public void Close() => _sqlConnection.Close();
      public IDbCommand CreateCommand() => _sqlConnection.CreateCommand();
      public void Open() => _sqlConnection.Open();
      public void Dispose() => _sqlConnection.Dispose();
   }
}

然后告诉 NLog DatabaseTarget 在 MyAssembly.dll 中使用您自定义的 MyDbConnection:

<target type="database" dbprovider="MyNameSpace.MyDbConnection, MyAssembly">
</target>

抱歉有任何编译器错误,因为我没有测试提供的代码,只是一个随机的想法。

另请参阅:https://www.devexpress.com/Support/Center/Question/Details/T711407/how-to-establish-sqlconnection-for-a-user-using-the-accesstoken-authentication

【讨论】:

  • 大声笑,我在这里对 MySql 感到困惑;)(MySqlConnection() 用于 SQL 服务器?!)
  • 更新代码,重命名为MyDbConnection(而不是MySqlConnection)
【解决方案4】:

Microsoft.Data.SqlClient 版本。 2.1.0 现在支持 ConnectionString 中的Authentication-option(无需显式分配 AccessToken):

string ConnectionString = @"Server=demo.database.windows.net; Authentication=Active Directory Default; Database=testdb;";

Active Directory Default 使用 Azure.Identity-package 中的 DefaultAzureCredential,它支持以下身份提供者:

  • EnvironmentCredential - 根据环境变量对 Azure Active Directory 进行身份验证。
  • ManagedIdentityCredential - 使用分配给部署环境的标识对 Azure Active Directory 进行身份验证。
  • SharedTokenCacheCredential - 使用 Microsoft 应用程序之间共享的本地缓存中的令牌进行身份验证。
  • VisualStudioCredential - 使用 Visual Studio 中的数据对 Azure Active Directory 进行身份验证
  • VisualStudioCodeCredential - 使用 Visual Studio Code 中的数据对 Azure Active Directory 进行身份验证
  • AzureCliCredential - 使用 Azure CLI 对 Azure Active Directory 进行身份验证以获取访问令牌

另见:Using Active Directory Default authentication

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2016-05-05
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多