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

riemer pushed a commit to branch 
2269-support-basic-auth-for-prometheus-monitoring-endpoint
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to 
refs/heads/2269-support-basic-auth-for-prometheus-monitoring-endpoint by this 
push:
     new 021b7f511 feat(#2269): Add basic auth to prometheus monitoring endpoint
021b7f511 is described below

commit 021b7f511f621394bfa1684009d64e16afd1cbde
Author: Dominik Riemer <[email protected]>
AuthorDate: Mon Dec 4 15:00:52 2023 +0100

    feat(#2269): Add basic auth to prometheus monitoring endpoint
---
 .../security/UnauthorizedRequestEntryPoint.java    |  2 +-
 .../core/filter/TokenAuthenticationFilter.java     | 43 +++++++++++++++++++++-
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git 
a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
 
b/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
index 144a990dc..94304a6d5 100644
--- 
a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
+++ 
b/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/security/UnauthorizedRequestEntryPoint.java
@@ -35,7 +35,7 @@ public class UnauthorizedRequestEntryPoint implements 
AuthenticationEntryPoint {
   @Override
   public void commence(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse,
                        AuthenticationException e) throws IOException {
-    LOG.error("Unauthorized request to {}", httpServletRequest.getPathInfo());
+    LOG.error("Unauthorized request to {}", 
httpServletRequest.getServletPath());
 
     httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, 
e.getLocalizedMessage());
   }
diff --git 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/filter/TokenAuthenticationFilter.java
 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/filter/TokenAuthenticationFilter.java
index e389f4afb..47f9dd018 100644
--- 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/filter/TokenAuthenticationFilter.java
+++ 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/filter/TokenAuthenticationFilter.java
@@ -24,11 +24,13 @@ import 
org.apache.streampipes.model.client.user.ServiceAccount;
 import org.apache.streampipes.model.client.user.UserAccount;
 import org.apache.streampipes.storage.api.IUserStorage;
 import org.apache.streampipes.storage.management.StorageDispatcher;
+import 
org.apache.streampipes.user.management.encryption.SecretEncryptionManager;
 import org.apache.streampipes.user.management.jwt.JwtTokenProvider;
 import org.apache.streampipes.user.management.model.PrincipalUserDetails;
 import org.apache.streampipes.user.management.model.ServiceAccountDetails;
 import org.apache.streampipes.user.management.model.UserAccountDetails;
 import org.apache.streampipes.user.management.service.TokenService;
+import org.apache.streampipes.user.management.util.PasswordUtil;
 import org.apache.streampipes.user.management.util.TokenUtil;
 
 import org.slf4j.Logger;
@@ -45,12 +47,20 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
 import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Base64;
+import java.util.List;
 
 public class TokenAuthenticationFilter extends OncePerRequestFilter {
 
   private final JwtTokenProvider tokenProvider;
   private final IUserStorage userStorage;
 
+  private final List<String> supportedBasicAuthPaths = List.of(
+      "/actuator/prometheus"
+  );
+
   private static final Logger logger = 
LoggerFactory.getLogger(TokenAuthenticationFilter.class);
 
   public TokenAuthenticationFilter() {
@@ -68,7 +78,7 @@ public class TokenAuthenticationFilter extends 
OncePerRequestFilter {
       if (StringUtils.hasText(jwt) && tokenProvider.validateJwtToken(jwt)) {
         String username = tokenProvider.getUserIdFromToken(jwt);
         applySuccessfulAuth(request, username);
-      } else {
+      } else if (isApiKeyAuth(request)) {
         String apiKey = getApiKeyFromRequest(request);
         String apiUser = getApiUserFromRequest(request);
         if (StringUtils.hasText(apiKey) && StringUtils.hasText(apiUser)) {
@@ -78,6 +88,22 @@ public class TokenAuthenticationFilter extends 
OncePerRequestFilter {
             applySuccessfulAuth(request, apiUser);
           }
         }
+      } else {
+        var authorizationHeader = request.getHeader("Authorization");
+        if (authorizationHeader != null && 
authorizationHeader.startsWith("Basic ")) {
+          if (supportedBasicAuthPaths.contains(request.getServletPath())) {
+            String base64Credentials = authorizationHeader.substring("Basic 
".length()).trim();
+            String credentials = new 
String(Base64.getDecoder().decode(base64Credentials));
+
+            String[] splitCredentials = credentials.split(":");
+            String username = splitCredentials[0];
+            String providedProperty = splitCredentials[1];
+            var principal = 
StorageDispatcher.INSTANCE.getNoSqlStore().getUserStorageAPI().getUser(username);
+            if (principal != null && checkCredentials(principal, 
providedProperty)) {
+              applySuccessfulAuth(request, username);
+            }
+          }
+        }
       }
     } catch (Exception ex) {
       logger.error("Could not set user authentication in security context", 
ex);
@@ -86,6 +112,21 @@ public class TokenAuthenticationFilter extends 
OncePerRequestFilter {
     filterChain.doFilter(request, response);
   }
 
+  private boolean checkCredentials(Principal principal, String 
providedProperty)
+      throws NoSuchAlgorithmException, InvalidKeySpecException {
+    if (principal instanceof UserAccount) {
+      return PasswordUtil.validatePassword(providedProperty, ((UserAccount) 
principal).getPassword());
+    } else if (principal instanceof ServiceAccount) {
+      return 
providedProperty.equals(SecretEncryptionManager.decrypt(((ServiceAccount) 
principal).getClientSecret()));
+    } else {
+      throw new IllegalArgumentException("Unknown user instance");
+    }
+  }
+
+  private boolean isApiKeyAuth(HttpServletRequest request) {
+    return request.getHeader(HttpConstants.X_API_USER) != null && 
request.getHeader(HttpConstants.X_API_KEY) != null;
+  }
+
   private void applySuccessfulAuth(HttpServletRequest request,
                                    String username) {
     Principal user = userStorage.getUser(username);

Reply via email to