Skip to content

Commit 3eb7ef0

Browse files
authored
Authenticator added for PrometheusHttpServer (#7225)
1 parent f801a15 commit 3eb7ef0

3 files changed

Lines changed: 75 additions & 3 deletions

File tree

exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
package io.opentelemetry.exporter.prometheus;
1212

13+
import com.sun.net.httpserver.Authenticator;
1314
import com.sun.net.httpserver.HttpHandler;
1415
import io.opentelemetry.sdk.common.CompletableResultCode;
1516
import io.opentelemetry.sdk.common.export.MemoryMode;
@@ -70,7 +71,8 @@ public static PrometheusHttpServerBuilder builder() {
7071
@Nullable Predicate<String> allowedResourceAttributesFilter,
7172
MemoryMode memoryMode,
7273
@Nullable HttpHandler defaultHandler,
73-
DefaultAggregationSelector defaultAggregationSelector) {
74+
DefaultAggregationSelector defaultAggregationSelector,
75+
@Nullable Authenticator authenticator) {
7476
this.builder = builder;
7577
this.prometheusMetricReader =
7678
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
@@ -99,6 +101,7 @@ public static PrometheusHttpServerBuilder builder() {
99101
.executorService(executor)
100102
.registry(prometheusRegistry)
101103
.defaultHandler(defaultHandler)
104+
.authenticator(authenticator)
102105
.buildAndStart();
103106
} catch (IOException e) {
104107
throw new UncheckedIOException("Could not create Prometheus HTTP server", e);

exporters/prometheus/src/main/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerBuilder.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static io.opentelemetry.api.internal.Utils.checkArgument;
99
import static java.util.Objects.requireNonNull;
1010

11+
import com.sun.net.httpserver.Authenticator;
1112
import com.sun.net.httpserver.HttpHandler;
1213
import io.opentelemetry.sdk.common.export.MemoryMode;
1314
import io.opentelemetry.sdk.metrics.InstrumentType;
@@ -36,6 +37,7 @@ public final class PrometheusHttpServerBuilder {
3637
@Nullable private HttpHandler defaultHandler;
3738
private DefaultAggregationSelector defaultAggregationSelector =
3839
DefaultAggregationSelector.getDefault();
40+
@Nullable private Authenticator authenticator;
3941

4042
PrometheusHttpServerBuilder() {}
4143

@@ -48,6 +50,7 @@ public final class PrometheusHttpServerBuilder {
4850
this.executor = builder.executor;
4951
this.memoryMode = builder.memoryMode;
5052
this.defaultAggregationSelector = builder.defaultAggregationSelector;
53+
this.authenticator = builder.authenticator;
5154
}
5255

5356
/** Sets the host to bind to. If unset, defaults to {@value #DEFAULT_HOST}. */
@@ -146,6 +149,17 @@ public PrometheusHttpServerBuilder setDefaultAggregationSelector(
146149
return this;
147150
}
148151

152+
/**
153+
* Set the authenticator for {@link PrometheusHttpServer}.
154+
*
155+
* <p>If unset, no authentication will be performed.
156+
*/
157+
public PrometheusHttpServerBuilder setAuthenticator(Authenticator authenticator) {
158+
requireNonNull(authenticator, "authenticator");
159+
this.authenticator = authenticator;
160+
return this;
161+
}
162+
149163
/**
150164
* Returns a new {@link PrometheusHttpServer} with the configuration of this builder which can be
151165
* registered with a {@link io.opentelemetry.sdk.metrics.SdkMeterProvider}.
@@ -166,6 +180,7 @@ public PrometheusHttpServer build() {
166180
allowedResourceAttributesFilter,
167181
memoryMode,
168182
defaultHandler,
169-
defaultAggregationSelector);
183+
defaultAggregationSelector,
184+
authenticator);
170185
}
171186
}

exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import com.linecorp.armeria.common.HttpMethod;
2222
import com.linecorp.armeria.common.HttpStatus;
2323
import com.linecorp.armeria.common.RequestHeaders;
24+
import com.sun.net.httpserver.Authenticator;
25+
import com.sun.net.httpserver.HttpExchange;
26+
import com.sun.net.httpserver.HttpPrincipal;
2427
import io.github.netmikey.logunit.api.LogCapturer;
2528
import io.opentelemetry.api.common.Attributes;
2629
import io.opentelemetry.api.metrics.DoubleHistogram;
@@ -528,6 +531,15 @@ void toBuilder() {
528531
PrometheusRegistry prometheusRegistry = new PrometheusRegistry();
529532
builder.setPrometheusRegistry(prometheusRegistry);
530533

534+
Authenticator authenticator =
535+
new Authenticator() {
536+
@Override
537+
public Result authenticate(HttpExchange exchange) {
538+
return new Success(new HttpPrincipal("anonymous", "public"));
539+
}
540+
};
541+
builder.setAuthenticator(authenticator);
542+
531543
PrometheusHttpServer httpServer = builder.build();
532544
PrometheusHttpServerBuilder fromOriginalBuilder = httpServer.toBuilder();
533545
httpServer.close();
@@ -538,7 +550,8 @@ void toBuilder() {
538550
.hasFieldOrPropertyWithValue("otelScopeEnabled", false)
539551
.hasFieldOrPropertyWithValue("allowedResourceAttributesFilter", resourceAttributesFilter)
540552
.hasFieldOrPropertyWithValue("executor", executor)
541-
.hasFieldOrPropertyWithValue("prometheusRegistry", prometheusRegistry);
553+
.hasFieldOrPropertyWithValue("prometheusRegistry", prometheusRegistry)
554+
.hasFieldOrPropertyWithValue("authenticator", authenticator);
542555
}
543556

544557
/**
@@ -611,4 +624,45 @@ void histogramDefaultBase2ExponentialHistogram() throws IOException {
611624
prometheusServer.shutdown();
612625
}
613626
}
627+
628+
@Test
629+
void authenticator() {
630+
// given
631+
try (PrometheusHttpServer prometheusServer =
632+
PrometheusHttpServer.builder()
633+
.setHost("localhost")
634+
.setPort(0)
635+
.setAuthenticator(
636+
new Authenticator() {
637+
@Override
638+
public Result authenticate(HttpExchange exchange) {
639+
if ("/metrics".equals(exchange.getRequestURI().getPath())) {
640+
return new Failure(401);
641+
} else {
642+
return new Success(new HttpPrincipal("anonymous", "public"));
643+
}
644+
}
645+
})
646+
.build()) {
647+
prometheusServer.register(
648+
new CollectionRegistration() {
649+
@Override
650+
public Collection<MetricData> collectAllMetrics() {
651+
return metricData.get();
652+
}
653+
});
654+
WebClient client =
655+
WebClient.builder("http://localhost:" + prometheusServer.getAddress().getPort())
656+
.decorator(RetryingClient.newDecorator(RetryRule.failsafe()))
657+
.build();
658+
659+
// when
660+
AggregatedHttpResponse metricsResponse = client.get("/metrics").aggregate().join();
661+
AggregatedHttpResponse defaultResponse = client.get("/").aggregate().join();
662+
663+
// then
664+
assertThat(metricsResponse.status()).isEqualTo(HttpStatus.UNAUTHORIZED);
665+
assertThat(defaultResponse.status()).isEqualTo(HttpStatus.OK);
666+
}
667+
}
614668
}

0 commit comments

Comments
 (0)