如何创建与Microsoft.azure.Management.compute一起使用的serviceclientcredential

时间:2016-02-05 15:42:07

标签: c# azure

我正在尝试使用C#以编程方式从Microsoft.Azure.Management.Compute检索托管服务。这需要ServiceClientCredential,我不知道如何获得它。谁能帮帮我吗?我可以使用Microsoft.WindowsAzure.Management.Compute来获取它们,但这里只返回ResourceManager下的实例而不是经典实例。

4 个答案:

答案 0 :(得分:13)

首先,您需要创建Active Directory应用程序。使用此链接创建AD应用{​​{3}}

示例代码使用Microsoft.Azure.Management.Compute 13.0.1-prerelease SDK 网址:https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/

public class CustomLoginCredentials : ServiceClientCredentials
    {  
        private string AuthenticationToken { get; set; }
        public override void InitializeServiceClient<T>(ServiceClient<T> client)
        {
            var authenticationContext =
                new AuthenticationContext("https://login.windows.net/{tenantID}");
            var credential = new ClientCredential(clientId: "xxxxx-xxxx-xx-xxxx-xxx", clientSecret: "{clientSecret}");

            var result = authenticationContext.AcquireToken(resource: "https://management.core.windows.net/",
                clientCredential: credential);

            if (result == null)
            {
                throw new InvalidOperationException("Failed to obtain the JWT token");
            }

            AuthenticationToken = result.AccessToken;
        }
  public override async Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request == null)
        {
            throw new ArgumentNullException("request");
        }

        if (AuthenticationToken == null)
        {
            throw new InvalidOperationException("Token Provider Cannot Be Null");
        }



        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AuthenticationToken);
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        //request.Version = new Version(apiVersion);
        await base.ProcessHttpRequestAsync(request, cancellationToken);

    }
}

以下是如何初始化客户端

 netClient = new Microsoft.Azure.Management.Compute.ComputeManagementClient(new CustomLoginCredentials());

        netClient.SubscriptionId = _subscriptionId;

答案 1 :(得分:2)

在游戏后期,但这就是我们在项目中执行此操作的方式。我们使用 .net 框架提供的令牌凭据来访问托管身份、visual studio(代码)身份或交互式身份。并连接到 azure 基础架构 API。

internal class CustomTokenProvider : ServiceClientCredentials
{
    private const string BearerTokenType = "Bearer";
    private TokenCredential _tokenCredential;
    private readonly string[] _scopes;
    private readonly IMemoryCache _cache;

    public CustomTokenProvider(TokenCredential tokenCredential, string[] scopes, IMemoryCache cache)
    {
        _tokenCredential = tokenCredential ?? throw new ArgumentNullException(nameof(tokenCredential));
        _scopes = scopes ?? throw new ArgumentNullException(nameof(scopes));
        _cache = cache;
    }

    public override async Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request == null)
        {
            throw new ArgumentNullException(nameof(request));
        }

        var token = await _cache.GetOrCreateAsync("accessToken-tokenProvider." + string.Join("#", _scopes), async e =>
        {
            var accessToken = await _tokenCredential.GetTokenAsync(new TokenRequestContext(_scopes), cancellationToken);
            e.AbsoluteExpiration = accessToken.ExpiresOn;
            return accessToken.Token;
        });
        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(BearerTokenType, token);
        await base.ProcessHttpRequestAsync(request, cancellationToken).ConfigureAwait(false);
    }
}

几点说明:

  • TokenCredential 类不会缓存令牌,如果您不这样做,它会因请求过多而触发 azure 错误。
  • 使用 v2 调用调用 v1 端点需要在范围内有点创意。因此,当您需要访问管理 API 时,请提供以下范围“https://management.core.windows.net/.default”,而不是指定的 user_impersonate 范围。这是由于不同端点上的一些内部转换造成的。并且“.default”范围始终可用,并且会为您提供

答案 2 :(得分:0)

您现在要执行的操作是使用ITokenProvider和Microsoft.Rest.TokenCredentials。

try:
    return BatchLog.objects.filter(batch_id=self.kwargs["pk"])[0]
except IndexError:
    raise Http404('No logs for this id')

然后在您的DI配置中

public class CustomTokenProvider : ITokenProvider
{
    private readonly CustomConfiguration _config;

    public CustomTokenProvider(CustomConfiguration config)
    {
        _config = config;
    }

    public async Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken)
    {
        // For app only authentication, we need the specific tenant id in the authority url
        var tenantSpecificUrl = $"https://login.microsoftonline.com/{_config.TenantId}/";

        // Create a confidential client to authorize the app with the AAD app
        IConfidentialClientApplication clientApp = ConfidentialClientApplicationBuilder
                                                                        .Create(_config.ClientId)
                                                                        .WithClientSecret(_config.ClientSecret)
                                                                        .WithAuthority(tenantSpecificUrl)
                                                                        .Build();
        // Make a client call if Access token is not available in cache
        var authenticationResult = await clientApp
            .AcquireTokenForClient(new List<string> { _config.Scope })
            .ExecuteAsync();


        return new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
    }
}

我的示例与Power BI一起使用,但是可以与需要访问ServiceClientCredentials的任何对象一起使用。

您可以将Nuget包Microsoft.Identity.Client用于IConfidentialClientApplication。

答案 3 :(得分:0)

作为@verbedr answered,您可以改编 Azure.Identity client library 中的 TokenCredential。 @antdev answered 你可以实现一个 Microsoft.Rest.ITokenProvider。另一种选择是将两种方法结合起来,如下所示:

using Azure.Core;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Rest
{
    /// Allows an Azure.Core.TokenCredential to be the Microsoft.Rest.ITokenProvider.
    public class TokenCredentialTokenProvider : Microsoft.Rest.ITokenProvider
    {
        readonly TokenCredential _tokenCredential;
        readonly string[] _scopes;

        public TokenCredentialTokenProvider(TokenCredential tokenCredential, string[] scopes)
        {
            _tokenCredential = tokenCredential;
            _scopes = scopes;
        }

        public async Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken)
        {
            var accessToken = await _tokenCredential.GetTokenAsync(new TokenRequestContext(_scopes), cancellationToken);
            return new AuthenticationHeaderValue("Bearer", accessToken.Token);
        }
    }
}

它没有缓存。如果需要,您可以创建一个 CachingTokenProvider 或类似的。这可以像这样使用:

            var tokenCredentials = new Azure.Identity.DefaultAzureCredential(new Azure.Identity.DefaultAzureCredentialOptions
            {
                AuthorityHost = Azure.Identity.AzureAuthorityHosts.AzurePublicCloud
            });

            var restTokenProvider = new Microsoft.Rest.TokenCredentialTokenProvider(tokenCredentials,
                new string[] { "https://management.core.windows.net/.default" }
            );

            var restTokenCredentials = new Microsoft.Rest.TokenCredentials(restTokenProvider);

            using var computeClient = new ComputeManagementClient(restTokenCredentials);
            // computeClient.BaseUri = // set if using another cloud
            computeClient.SubscriptionId = subscriptionId;
            var vms = computeClient.VirtualMachines.ListAll();
            Console.WriteLine("# of vms " + vms.Count());

这对我有用。以下是我使用的 csproj 中的相关依赖项:

    <PackageReference Include="Azure.Identity" Version="1.4.0" />
    <PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.23" />
    <PackageReference Include="Microsoft.Azure.Management.Compute" Version="46.0.0" />