Azure Function 中的 HTTP 客户端未设置或使用证书

问题描述 投票:0回答:1

我有一个 Azure 函数,我在其中创建了一个 HTTP 客户端。该客户需要证书。该证书存储在 Azure KeyVault 中。在生产环境中,我在Azure功能的Application Insights中不断收到以下错误:

消息:结果:函数“MyDummyFunction” 调用引发了异常。异常:System.Net.Http.HttpRequestException:无法建立 SSL 连接,请参阅内部异常。 ---> System.Security.Authentication.AuthenticationException:身份验证失败,请参阅内部异常。 ---> Interop+OpenSsl+SslException:SSL 握手失败,出现 OpenSSL 错误 - SSL_ERROR_SSL。

这是我尝试设置证书的方式。

public class DummyHttpClient
{
    public readonly HttpClient client;

    private readonly ILogger<DummyHttpClient> logger;
    private readonly ActivationConfiguration configuration;

    public DummyHttpClient(ActivationConfiguration configuration, ILogger<DummyHttpClient> logger)
    {
        this.logger = logger;
        this.configuration = configuration;

        var handler = ClientHandlerConfigure();
        this.client = ClientConfigure(handler);
    }

    private HttpClientHandler ClientHandlerConfigure()
    {
        var certificate = GetCertificate();

        var handler = new HttpClientHandler()
        {
            SslProtocols = SslProtocols.Tls12,
            ClientCertificateOptions = ClientCertificateOption.Manual,
            ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return true; },
        };

        if (certificateForBHN is not null)
        {
            handler.ClientCertificates.Add(certificate);
        }

        return handler;
    }

    private HttpClient ClientConfigure(HttpClientHandler handler)
    {
        var client = new HttpClient(handler)
        {
            BaseAddress = new Uri(configuration.ApiBaseAddress),
            Timeout = TimeSpan.FromSeconds(100),
        };

        client.DefaultRequestHeaders.Add("ContentType", "application/json");
        client.DefaultRequestHeaders.Add("Accept", "application/json");
        client.DefaultRequestHeaders.ConnectionClose = false;

        return client;
    }

    private X509Certificate2 GetCertificate()
    {
            var client = new CertificateClient(new Uri($"https://dummykeyvault.vault.azure.net/"), new DefaultAzureCredential());

            var certificateOptions = new DownloadCertificateOptions("Activation")
            {
                KeyStorageFlags = X509KeyStorageFlags.MachineKeySet,
            };

            var certificate = client.DownloadCertificate(certificateOptions);

            return certificate.Value;
    }
}
c# azure azure-functions ssl-certificate azure-keyvault
1个回答
0
投票

我已按照以下步骤操作并能够在 Azure 中运行您的代码。

代码片段:

public class DummyHttpClient
{
    public readonly HttpClient client;

    private readonly ILogger<DummyHttpClient> logger;
    private readonly ActivationConfiguration configuration;

    public DummyHttpClient(ActivationConfiguration configuration, ILogger<DummyHttpClient> logger)
    {
        this.logger = logger;
        this.configuration = configuration;

        var handler = ClientHandlerConfigure();
        this.client = ClientConfigure(handler);
    }

    private HttpClientHandler ClientHandlerConfigure()
    {
        var certificate = GetCertificate();
        var handler = new HttpClientHandler
        {
            SslProtocols = SslProtocols.Tls12,
            ClientCertificateOptions = ClientCertificateOption.Manual,
            ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, certChain, policyErrors) => true,
        };

        if (certificate != null)
        {
            handler.ClientCertificates.Add(certificate);
        }

        return handler;
    }

    private HttpClient ClientConfigure(HttpClientHandler handler)
    {
        var client = new HttpClient(handler)
        {
            BaseAddress = new Uri(configuration.ApiBaseAddress),
            Timeout = TimeSpan.FromSeconds(100),
        };

        client.DefaultRequestHeaders.Add("ContentType", "application/json");
        client.DefaultRequestHeaders.Add("Accept", "application/json");
        client.DefaultRequestHeaders.ConnectionClose = false;

        return client;
    }

    private X509Certificate2 GetCertificate()
    {
        var client = new CertificateClient(new Uri("https://keyvault.vault.azure.net/"), new DefaultAzureCredential());
        var certificateName = "certificate_name";
        var certificateWithPolicy = client.GetCertificate(certificateName);
        var downloadOptions = new DownloadCertificateOptions(certificateWithPolicy.Value.Name)
        {
            KeyStorageFlags = X509KeyStorageFlags.MachineKeySet,
        };
        var certificate = client.DownloadCertificate(downloadOptions);
       return new X509Certificate2(certificate.Value);
    }
}

功能代码:

public class Function1
{
   private readonly ILogger<Function1> _logger;
   private readonly DummyHttpClient _dummyHttpClient;

   public Function1(ILogger<Function1> logger, DummyHttpClient dummyHttpClient)
   {
      _logger = logger;
      _dummyHttpClient = dummyHttpClient;
   }

[Function("Function1")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
  {
    var response = _dummyHttpClient.client.GetAsync("items");
    _logger.LogInformation("C# HTTP trigger function processed a request.");
    return new OkObjectResult("Welcome to Azure Functions!");
   }
}

在Azure功能应用程序中启用系统身份

enter image description here

Key Vault Administrator
Key Vault Certificates Officer
角色分配给函数应用程序:

enter image description here

传送门:

2024-10-28T12:36:24Z [Information] C# HTTP trigger function processed a request.
2024-10-28T12:36:24Z [Information] Executing OkObjectResult, writing value of type 'System.String'.
2024-10-28T12:36:24Z [Information] Executed 'Functions.Function1' (Succeeded, Id=5848e8b2-c933-4056-a0c8-33a88d827180, Duration=3000ms)

调用日志:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.