【问题标题】:Using AzureCredentialsFactory.FromServicePrincipal with a certificate throws System.NullReferenceException将 AzureCredentialsFactory.FromServicePrincipal 与证书一起使用会引发 System.NullReferenceException
【发布时间】:2020-10-29 07:38:46
【问题描述】:

我使用 .NET 框架 4.7.2 创建了一个控制台应用程序,以使用这些 nuget 包连接到 Azure 资源管理器 API:

  • Microsoft.Azure.Management.ResourceManager.Fluent:v1.18.0 | download link
  • Microsoft.Azure.Management.Fluent:v1.18.0 | download link

这是代码:

using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using System;
using System.Security.Cryptography.X509Certificates;

namespace AzResourceManager
{
    class Program
    {
        static void Main(string[] args)
        {
            var clientId = "********-****-****-****-************";
            var subscriptionId = "********-****-****-****-************";
            var tenantId = "********-****-****-****-************"; 
            var cert = GetCertificate("********************************");

            var creds = new AzureCredentialsFactory().FromServicePrincipal(clientId, cert, tenantId, AzureEnvironment.AzureGlobalCloud);
            var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId);

            foreach (var rGroup in azure.ResourceGroups.List())
            {
                Console.WriteLine(rGroup.Name);
            }
        }

        private static X509Certificate2 GetCertificate(string thumbPrint)
        {
            var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            certStore.Open(OpenFlags.ReadOnly);
            try
            {
                var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbPrint, false);
                if (certCollection.Count <= 0)
                    throw new InvalidOperationException("Unable to load certificate from store");
                return certCollection[0];
            }
            finally
            {
                certStore.Close();
            }
        }
    }
}

当执行到这一行时

foreach (var rGroup in azure.ResourceGroups.List())

应用程序抛出一个System.NullReferenceException: 'Object reference not set to an instance of an object.'

我在 Azure Active Directory 中注册的应用程序和我的笔记本电脑中安装了证书。我尝试更新一些软件包,但结果是一样的。我唯一不能更新到最新版本的包是Microsoft.IdentityModel.Clients.ActiveDirectory(最新版本:v4.4.1),我只能更新到版本v3.19.8

这是该异常的堆栈跟踪:

at Microsoft.Rest.Azure.Authentication.ClientAssertionCertificate.Sign(String message)\r\n   
at Microsoft.IdentityModel.Clients.ActiveDirectory.JsonWebToken.Sign(IClientAssertionCertificate credential) in c:\\workspace\\azure-activedirectory-library-for-dotnet-v3-master-VS2017\\src\\ADAL.PCL\\ClientCreds\\JsonWebToken.cs:line 100\r\n   
at Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey.AddToParameters(IDictionary`2 parameters) in c:\\workspace\\azure-activedirectory-library-for-dotnet-v3-master-VS2017\\src\\ADAL.PCL\\ClientCreds\\ClientKey.cs:line 127\r\n   
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<SendTokenRequestAsync>d__64.MoveNext() in c:\\workspace\\azure-activedirectory-library-for-dotnet-v3-master-VS2017\\src\\ADAL.PCL\\Flows\\AcquireTokenHandlerBase.cs:line 0\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n   

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)\r\n   
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<RunAsync>d__55.MoveNext() in c:\\workspace\\azure-activedirectory-library-for-dotnet-v3-master-VS2017\\src\\ADAL.PCL\\Flows\\AcquireTokenHandlerBase.cs:line 198\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n   

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenForClientCommonAsync>d__49.MoveNext() in c:\\workspace\\azure-activedirectory-library-for-dotnet-v3-master-VS2017\\src\\ADAL.PCL\\AuthenticationContext.cs:line 541\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n   

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenAsync>d__27.MoveNext() in c:\\workspace\\azure-activedirectory-library-for-dotnet-v3-master-VS2017\\src\\ADAL.PCL\\AuthenticationContext.cs:line 239\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n   

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.Rest.Azure.Authentication.CertificateAuthenticationProvider.<AuthenticateAsync>d__3.MoveNext()\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n   

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__33.MoveNext()\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n   

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__24.MoveNext()\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n  

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)\r\n   
at Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials.<ProcessHttpRequestAsync>d__24.MoveNext()\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)\r\n   at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsOperations.<ListWithHttpMessagesAsync>d__11.MoveNext()\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n 

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsOperationsExtensions.<ListAsync>d__6.MoveNext()\r\n
--- End of stack trace from previous location where exception was thrown ---\r\n

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.Extensions.Synchronize[TResult](Func`1 function)\r\n   
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsImpl.List()\r\n   
at AzResourceManager.Program.Main(String[] args) in D:\\Demos\\ARM\\AzResourceManager\\AzResourceManager\\Program.cs:line 27

如果我使用 secret 而不是证书,则代码可以正常工作。

using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using System;
using System.Security.Cryptography.X509Certificates;

namespace AzResourceManager
{
    class Program
    {
        static void Main(string[] args)
        {
            var clientId = "********-****-****-****-************";
            var secret = "********-****-****-****-************";
            var subscriptionId = "********-****-****-****-************";
            var tenantId = "********-****-****-****-************"; 

            var creds = new AzureCredentialsFactory().FromServicePrincipal(clientId, secret, tenantId, AzureEnvironment.AzureGlobalCloud);            
            var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId);

            foreach (var rGroup in azure.ResourceGroups.List())
            {
                Console.WriteLine(rGroup.Name);
            }
        }
    }
}

这些是安装的包:(packages.config)

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Azure.KeyVault" version="3.0.1" targetFramework="net472" />
  <package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net472" />
  <package id="Microsoft.Azure.KeyVault.WebKey" version="3.0.1" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.AppService.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Batch.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.BatchAI.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Cdn.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Compute.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.ContainerInstance.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.ContainerRegistry.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.ContainerService.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.CosmosDB.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Dns.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.EventHub.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Graph.RBAC.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.KeyVault.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Locks.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Monitor.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Msi.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Network.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Redis.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.ResourceManager.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Search.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.ServiceBus.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Sql.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.Storage.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Azure.Management.TrafficManager.Fluent" version="1.18.0" targetFramework="net472" />
  <package id="Microsoft.Data.Edm" version="5.8.2" targetFramework="net472" />
  <package id="Microsoft.Data.OData" version="5.8.2" targetFramework="net472" />
  <package id="Microsoft.Data.Services.Client" version="5.8.2" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.14.0" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Logging" version="1.1.2" targetFramework="net472" />
  <package id="Microsoft.IdentityModel.Tokens" version="5.1.2" targetFramework="net472" />
  <package id="Microsoft.Rest.ClientRuntime" version="2.3.17" targetFramework="net472" />
  <package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.18" targetFramework="net472" />
  <package id="Microsoft.Rest.ClientRuntime.Azure.Authentication" version="2.3.4" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net472" />
  <package id="System.ComponentModel.EventBasedAsync" version="4.0.11" targetFramework="net472" />
  <package id="System.Dynamic.Runtime" version="4.0.0" targetFramework="net472" />
  <package id="System.Linq.Queryable" version="4.0.0" targetFramework="net472" />
  <package id="System.Net.Requests" version="4.0.11" targetFramework="net472" />
  <package id="System.Spatial" version="5.8.2" targetFramework="net472" />
  <package id="WindowsAzure.Storage" version="8.1.4" targetFramework="net472" />
</packages>

【问题讨论】:

  • 您的租户是否可能无法访问某些订阅?您可以使用 get-azurermcontext -ListAvailable 来查看列表

标签: c# azure azure-active-directory azure-resource-manager x509certificate2


【解决方案1】:

您能否使用Resource Groups List REST API 获得结果。我已经尝试过自己,并且在使用您的代码时没有收到任何错误,并且对我来说效果很好。请确保已为您注册的应用程序服务主体提供了至少对您的订阅的读者访问权限。请按照文档Manage access using RBAC and the Azure portal 为 Azure 资源分配角色。

【讨论】:

    【解决方案2】:

    在尝试使用带有 .CER 扩展名的导出证书时,我遇到了同样令人沮丧的 System.NullReferenceException, 但是当导出带有密码的.PFX格式的证书时:重载的FromServicePrincipal函数成功

    var credentials = SdkContext
            .AzureCredentialsFactory
            .FromServicePrincipal(
                 "********-****-****-****-************", // clientId
                  @"c:\cert.pfx", // certificate file path
                 "123456", // certificate password
                 "********-****-****-****-************", //tenantId
                 AzureEnvironment.AzureGlobalCloud);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 2012-09-01
      • 2011-02-16
      • 1970-01-01
      • 2021-06-07
      • 2018-11-24
      • 2010-12-24
      相关资源
      最近更新 更多