将AzureCredentialsFactory.FromServicePrincipal与证书一起使用会引发Syste



我使用.NET框架4.7.2创建了一个控制台应用程序,以使用以下nuget包连接到Azure Resource Manager API:

  • Microsoft.Azure.Management.ResourceManager.Fluent:v1.18.0 |下载链接
  • Microsoft.Azure.Management.Fluent:v1.18.0 |下载链接

这是代码:

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)rn   
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 100rn   
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 127rn   
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 0rn
--- End of stack trace from previous location where exception was thrown ---rn   
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)rn   
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 198rn
--- End of stack trace from previous location where exception was thrown ---rn   
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
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 541rn
--- End of stack trace from previous location where exception was thrown ---rn   
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
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 239rn
--- End of stack trace from previous location where exception was thrown ---rn   
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at Microsoft.Rest.Azure.Authentication.CertificateAuthenticationProvider.<AuthenticateAsync>d__3.MoveNext()rn
--- End of stack trace from previous location where exception was thrown ---rn   
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__33.MoveNext()rn
--- End of stack trace from previous location where exception was thrown ---rn   
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__24.MoveNext()rn
--- End of stack trace from previous location where exception was thrown ---rn  
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)rn   
at Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials.<ProcessHttpRequestAsync>d__24.MoveNext()rn
--- End of stack trace from previous location where exception was thrown ---rn
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)rn   at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsOperations.<ListWithHttpMessagesAsync>d__11.MoveNext()rn
--- End of stack trace from previous location where exception was thrown ---rn 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsOperationsExtensions.<ListAsync>d__6.MoveNext()rn
--- End of stack trace from previous location where exception was thrown ---rn
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn   
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn   
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.Extensions.Synchronize[TResult](Func`1 function)rn   
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsImpl.List()rn   
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>

您是否能够使用Resource Groups List REST API获得结果。我已经尝试过了,在使用您的代码时没有出现任何错误,对我来说效果很好。请确保您的注册应用程序服务主体至少可以通过阅读器访问您的订阅。请按照文档"使用RBAC管理访问"和Azure门户为Azure资源分配角色。

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

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

最新更新