Azure Application Insights - 使用基本身份验证进行可用性测试?

Azure Application Insights - availability testing with basic auth?

我正在尝试在需要基本身份验证的端点上使用 Azure Application Insights 设置可用性测试(URL Ping 测试)。似乎标准方法与 https://username:password@myendpoint.com 未被 Azure 接受(错误消息显示 URL 格式错误,可能我在开头缺少 https/http)。

假设我想留在 Azure 生态系统中,除了使用多步 Web 测试或 Azure Functions 之外,还有其他方法可以实现此目的吗? :)

在 URL 中传递基本身份验证凭据已被 RFC 3986 弃用(这是 RFC 中的一个片段)

3.2.1. User Information

The userinfo subcomponent may consist of a user name and, optionally, scheme-specific information about how to gain authorization to access the resource. The user information, if present, is followed by a commercial at-sign ("@") that delimits it from the host.

  userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )

Use of the format "user:password" in the userinfo field is deprecated.

替代方法是使用 授权 header 来传递凭据。这是 Wikipedia (Basic Auth) 中关于如何构建 header 的片段。

The Authorization field is constructed as follows:[6]

  1. The username and password are combined with a single colon. (:)
  2. The resulting string is encoded into an octet sequence.[7]
  3. The resulting string is encoded using a variant of Base64.[8]
  4. The authorization method and a space is then prepended to the encoded string, separated with a space (e.g. "Basic ").

For example, if the browser uses Aladdin as the username and OpenSesame as the password, then the field's value is the base64-encoding of Aladdin:OpenSesame, or QWxhZGRpbjpPcGVuU2VzYW1l. Then the Authorization header will appear as:

Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l

您可以在 Visual Studio Enterprise 中创建一个 Web 测试 文件,然后将其上传到 Application insights 并使用它。请参阅此文档:https://docs.microsoft.com/en-us/azure/application-insights/app-insights-monitor-web-app-availability

  1. 在Visual StudioEnterprise中,您可以创建一个WebTest项目。
  2. 右键单击您的项目名称并select 添加请求
  3. 现在右键单击 link 和 select 添加 Header
  4. 您可以根据需要添加 header。
  5. 当您查看 .webtest 文件时,您会看到 Headers 部分附加在 Requests 下。
<Request>
  <Headers>
    <Header Name="Authorization" Value="Basic QWxhZGRpbjpPcGVuU2VzYW1l" />
  </Headers>
</Request>

Ping 测试应该相对简单,目前有几种方法可以防止此类 url 匿名访问,例如策略或操作过滤器。

基于策略的授权

让我们创建一个简单的策略,它需要查询字符串中的密钥。

首先,使用处理程序创建需求,例如:

public class HasSecretKeyRequirement : IAuthorizationRequirement
{
}

public class HasSecretKeyRequirementHandler : AuthorizationHandler<HasSecretKeyRequirement>
{
   private readonly IHttpContextAccessor _httpContextAccessor;
   private readonly IConfiguration _configuration;

   public HasSecretKeyRequirementHandler(IHttpContextAccessor httpContextAccessor, IConfiguration configuration)
   {
       _httpContextAccessor = httpContextAccessor;
       _configuration = configuration;
   }

   protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasApiKeyRequirement requirement)
   {
       var httpContext = _httpContextAccessor.HttpContext;
            
       if (httpContext == null)
       {
           context.Fail();
           return Task.CompletedTask;
       }
            
       if (httpContext.Request.Query.TryGetValue("SecretKey", out extractedSecretKey))
       {
           var secretKey= _configuration.GetValue<string>("SecretKey");
 
           if (secretKey.Equals(extractedSecretKey))
           {
               context.Succeed(requirement);
               return Task.CompletedTask;
           }
        }
            
        httpContext.Response.ContentType = "text/plain";
        httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    
        context.Fail();
        return Task.CompletedTask;  
    }
}

然后使用需求创建新策略并注册需求处理程序:

services.AddAuthorization(options =>
{
   options.AddPolicy("HasSecretKey", policy =>
      policy.Requirements.Add(new HasSecretKeyRequirement()));
);

services.AddSingleton<IAuthorizationHandler, HasSecretKeyRequirementHandler>();

将策略应用于您的 ping 端点:

[Authorize(Policy = "HasSecretKey")]
[HttpGet("api/ping")]
public IActionResult Ping()
{
   return Ok();
}

Finalldd 配置您的可用性测试:

https://yourapi.com/api/ping?SecretKey=yoursecretkey

这只是一个示例,您可以创建自己的需求和处理逻辑。您可以在您的应用程序中重用这些策略,例如在健康检查端点中:

endpoints.MapHealthChecks("/health")
    .RequireAuthorization("HasSecretKey");

这种形式的授权在这种简单的情况下可能就足够了,但绝对不应该在更高级的场景中使用。

供参考:根据上面@kaushal 的回答中的片段,我能够扩展基本 URL Ping 测试 :) 我在 Terraform but you can also submit this via the REST API 中使用 XML直接地。在我的例子中,我需要添加一个任意的 header

<WebTest Name="appinsights-webtest" Id="ABD48585-0831-40CB-9069-682EA6BB3583" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="30" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
  <Items>
    <Request Method="GET" Guid="a5f10126-e4cd-570d-961c-cea43999a200" Version="1.1" Url="https://example.com/health/stamp" ThinkTime="0" Timeout="30" ParseDependentRequests="False" FollowRedirects="False" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="200" ExpectedResponseUrl="" ReportingName="" IgnoreHttpStatusCode="False">
      <Headers>
        <Header Name="X-Azure-FDID" Value="xxxxxxxxxxxx-xxxxxxxx-xxx" />
      </Headers>
  </Request>
  </Items>
</WebTest>

我没有在任何地方找到这个文档,但对我来说工作正常。