This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new cbea8af5746 HDDS-14149. Fix possible StringIndexOutOfBoundsException 
in PrometheusServlet (#9603)
cbea8af5746 is described below

commit cbea8af57461aeb09389237afd1238e65fb93c68
Author: Navink <[email protected]>
AuthorDate: Fri Jan 9 21:08:14 2026 +0530

    HDDS-14149. Fix possible StringIndexOutOfBoundsException in 
PrometheusServlet (#9603)
---
 .../hadoop/hdds/server/http/PrometheusServlet.java |   4 +-
 .../http/TestPrometheusServletAuthorization.java   | 110 +++++++++++++++++++++
 2 files changed, 112 insertions(+), 2 deletions(-)

diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/PrometheusServlet.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/PrometheusServlet.java
index ccf624645c9..a58af8abe18 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/PrometheusServlet.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/http/PrometheusServlet.java
@@ -32,7 +32,7 @@
 public class PrometheusServlet extends HttpServlet {
 
   public static final String SECURITY_TOKEN = "PROMETHEUS_SECURITY_TOKEN";
-  public static final String BEARER = "Bearer";
+  public static final String BEARER = "Bearer ";
 
   public PrometheusMetricsSink getPrometheusSink() {
     return
@@ -50,7 +50,7 @@ protected void doGet(HttpServletRequest req, 
HttpServletResponse resp)
       if (authorizationHeader == null
           || !authorizationHeader.startsWith(BEARER)
           || !securityToken.equals(
-              authorizationHeader.substring(BEARER.length() + 1))) {
+              authorizationHeader.substring(BEARER.length()))) {
         resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
         return;
       }
diff --git 
a/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestPrometheusServletAuthorization.java
 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestPrometheusServletAuthorization.java
new file mode 100644
index 00000000000..ef2dc6884f6
--- /dev/null
+++ 
b/hadoop-hdds/framework/src/test/java/org/apache/hadoop/hdds/server/http/TestPrometheusServletAuthorization.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hdds.server.http;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.stream.Stream;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * Tests authorization behavior of {@link PrometheusServlet}.
+ */
+public class TestPrometheusServletAuthorization {
+
+  private static final String SECURITY_TOKEN = "mytoken";
+  private PrometheusServlet servlet;
+  private PrometheusMetricsSink sink;
+
+  @BeforeEach
+  public void setup() throws Exception {
+    sink = mock(PrometheusMetricsSink.class);
+    servlet = new PrometheusServlet();
+    ServletContext context = mock(ServletContext.class);
+    when(context.getAttribute(PrometheusServlet.SECURITY_TOKEN))
+        .thenReturn(SECURITY_TOKEN);
+    when(context.getAttribute(BaseHttpServer.PROMETHEUS_SINK))
+        .thenReturn(sink);
+    ServletConfig config = mock(ServletConfig.class);
+    when(config.getServletContext()).thenReturn(context);
+
+    servlet.init(config);
+  }
+
+  /**
+   * Prepare tests data.
+   * @return Invalid authorization header values.
+   */
+  private static Stream<String> invalidAuthorizationHeaders() {
+    return Stream.of(
+        null,
+        "Bearer",
+        "Bearer ",
+        "Bearer wrongToken"
+    );
+  }
+
+  private HttpServletResponse invokeServlet(
+      String authorizationHeader) throws Exception {
+    HttpServletRequest req = mock(HttpServletRequest.class);
+    when(req.getHeader("Authorization"))
+        .thenReturn(authorizationHeader);
+    HttpServletResponse resp = mock(HttpServletResponse.class);
+    when(resp.getWriter())
+        .thenReturn(new PrintWriter(new StringWriter()));
+    servlet.doGet(req, resp);
+    return resp;
+  }
+
+  @Test
+  public void testValidBearerTokenAllowsPrometheusAccess() throws Exception {
+    HttpServletResponse resp =
+        invokeServlet("Bearer mytoken");
+    //verify writeMetrics() was called only once.
+    verify(sink).writeMetrics(any());
+    //verify setStatus(403) was never called.
+    verify(resp, never())
+        .setStatus(HttpServletResponse.SC_FORBIDDEN);
+  }
+
+  @ParameterizedTest(name = "Invalid Authorization header [{0}] must return 
403")
+  @MethodSource("invalidAuthorizationHeaders")
+  public void testInvalidAuthorizationHeadersReturn403(
+      String authorizationHeader) throws Exception {
+    HttpServletResponse resp =
+        invokeServlet(authorizationHeader);
+    //verify setStatus(403) was called only once.
+    verify(resp)
+        .setStatus(HttpServletResponse.SC_FORBIDDEN);
+    //verify writeMetrics() was never called.
+    verify(sink, never()).writeMetrics(any());
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to