FireShock
FireShock

Reputation: 1122

Authenticate ASP.NET Core OpenTelemetry /metrics endpoint

app.UseOpenTelemetryPrometheusScrapingEndpoint(); adds an endpoint /metrics where Prometheus scrapes collected metrics. The endpoint, however, does not have any autentication and can be called by everyone.

Is there a configuration for the endpoint to add some basic or custom autentication?

Upvotes: 1

Views: 2172

Answers (3)

adamskey
adamskey

Reputation: 68

I recently faced a similar issue while setting up telemetry for an application. I ended up doing the following:

  1. Create and register a custom authentication scheme which does the basic auth of incoming requests to the /metrics endpoint
  2. The UseOpenTelemetryPrometheusScrapingEndpoint method allows the request to be handled by a branched pipeline, which can be configured with arbitrary middleware. I created a middleware which calls AuthenticateAsync and uses my custom auth scheme on the incoming http context. If the request is successfully authenticated, the next delegate is invoked and request is handled, if not, the status code of the response is set to 401 and no data is returned.

This approach returns the proper status code for requests with invalid credentials. In contrast, running the auth code in the predicate will return 404 - false result of the predicate means 'do not branch the pipeline, endpoint /metrics does not exist'.

Upvotes: 0

Googi
Googi

Reputation: 598

Having Authentication enabled for metrics endpoint is one way , Have you considered another commonly used approach ->

Creating a separate web server endpoint, such as a new instance of KestrelMetricServer, on a different port. Access to this endpoint is restricted by firewall rules, allowing only specific IP addresses to connect. For a practical example, you can refer to the sample available on GitHub.

In this approach, the Prometheus metrics are exposed via a separate HTTP server, running alongside the main application. By configuring the firewall to only allow access from specific IP addresses, you can ensure that the metrics are accessible only to authorized parties. This provides an additional layer of security for your metrics endpoint.

Upvotes: 4

Brad
Brad

Reputation: 10680

UseOpenTelemetryPrometheusScrapingEndpoint() lets you provide a predicate which returns true or false to serve the metrics endpoint or not. You can use the predicate to check authorization headers and then block or grant the request.

For example, you can check the Basic Authorization headers in the predicate as described here: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/basic-authentication

app.UseOpenTelemetryPrometheusScrapingEndpoint(
    context =>
    {
        if (context.Request.Path != "/metrics") return false;
        var authHeader = context.Request.Headers.Authorization.FirstOrDefault();
        if (authHeader == null) return false;
        var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
        if (authHeaderVal == null) return false;
        // RFC 2617 sec 1.2, "scheme" name is case-insensitive
        if (!authHeaderVal.Scheme.Equals("basic",
                        StringComparison.OrdinalIgnoreCase) ||
             authHeaderVal.Parameter == null)
        {
            return false;
        }
        var encoding = Encoding.GetEncoding("iso-8859-1");
        var credentials = encoding.GetString(Convert.FromBase64String(authHeaderVal.Parameter));
        int separator = credentials.IndexOf(':');
        string name = credentials.Substring(0, separator);
        string password = credentials.Substring(separator + 1);
        return name == "your_username" && password == "your_password";
    });

Of course then your prometheus config must also match the basic auth credentials:

    basic_auth: 
      username: your_username
      password: your_password

Upvotes: 4

Related Questions