iliax 1 rok pred
rodič
commit
3bc578bd90

+ 1 - 1
kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AccessController.java

@@ -32,7 +32,7 @@ public class AccessController implements AuthorizationApi {
   private final AccessControlService accessControlService;
 
   public Mono<ResponseEntity<AuthenticationInfoDTO>> getUserAuthInfo(ServerWebExchange exchange) {
-    Mono<List<UserPermissionDTO>> permissions = accessControlService.getUser()
+    Mono<List<UserPermissionDTO>> permissions = AccessControlService.getUser()
         .map(user -> accessControlService.getRoles()
             .stream()
             .filter(role -> user.groups().contains(role.getName()))

+ 2 - 2
kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/rbac/AccessContext.java

@@ -70,9 +70,9 @@ public record AccessContext(String cluster,
     return new AccessContextBuilder();
   }
 
-  public boolean isAccessible(List<Permission> allUserPermissions) {
+  public boolean isAccessible(List<Permission> userPermissions) {
     return accesses().stream()
-        .allMatch(resourceAccess -> resourceAccess.isAccessible(allUserPermissions));
+        .allMatch(resourceAccess -> resourceAccess.isAccessible(userPermissions));
   }
 
   public static final class AccessContextBuilder {

+ 5 - 20
kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/audit/AuditService.java

@@ -11,6 +11,7 @@ import com.provectus.kafka.ui.model.rbac.AccessContext;
 import com.provectus.kafka.ui.service.AdminClientService;
 import com.provectus.kafka.ui.service.ClustersStorage;
 import com.provectus.kafka.ui.service.ReactiveAdminClient;
+import com.provectus.kafka.ui.service.rbac.AccessControlService;
 import java.io.Closeable;
 import java.io.IOException;
 import java.time.Duration;
@@ -20,7 +21,6 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
-import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.kafka.clients.producer.KafkaProducer;
@@ -28,9 +28,7 @@ import org.apache.kafka.clients.producer.ProducerConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.stereotype.Service;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.Signal;
@@ -181,31 +179,18 @@ public class AuditService implements Closeable {
 
   public void audit(AccessContext acxt, Signal<?> sig) {
     if (sig.isOnComplete()) {
-      extractUser(sig)
+      extractUser()
           .doOnNext(u -> sendAuditRecord(acxt, u))
           .subscribe();
     } else if (sig.isOnError()) {
-      extractUser(sig)
+      extractUser()
           .doOnNext(u -> sendAuditRecord(acxt, u, sig.getThrowable()))
           .subscribe();
     }
   }
 
-  private Mono<AuthenticatedUser> extractUser(Signal<?> sig) {
-    //see ReactiveSecurityContextHolder for impl details
-    Object key = SecurityContext.class;
-    if (sig.getContextView().hasKey(key)) {
-      return sig.getContextView().<Mono<SecurityContext>>get(key)
-          .map(context -> context.getAuthentication().getPrincipal())
-          .cast(UserDetails.class)
-          .map(user -> {
-            var roles = user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
-            return new AuthenticatedUser(user.getUsername(), roles);
-          })
-          .switchIfEmpty(NO_AUTH_USER);
-    } else {
-      return NO_AUTH_USER;
-    }
+  private Mono<AuthenticatedUser> extractUser() {
+    return AccessControlService.getUser().switchIfEmpty(NO_AUTH_USER);
   }
 
   private void sendAuditRecord(AccessContext ctx, AuthenticatedUser user) {

+ 39 - 62
kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/rbac/AccessControlService.java

@@ -91,33 +91,33 @@ public class AccessControlService {
   }
 
   public Mono<Void> validateAccess(AccessContext context) {
+    return isAccessible(context)
+        .flatMap(allowed -> allowed ? Mono.empty() : Mono.error(new AccessDeniedException(ACCESS_DENIED)))
+        .then();
+  }
+
+  private Mono<Boolean> isAccessible(AccessContext context) {
     if (!rbacEnabled) {
-      return Mono.empty();
+      return Mono.just(true);
     }
-    return getUser()
-        .flatMap(user -> {
-          if (!isAccessible(user, context)) {
-            return Mono.error(new AccessDeniedException(ACCESS_DENIED));
-          }
-          return Mono.empty();
-        })
-        .then();
+    return getUser().map(user -> isAccessible(user, context));
   }
 
   private boolean isAccessible(AuthenticatedUser user, AccessContext context) {
     if (context.cluster() != null && !isClusterAccessible(context.cluster(), user)) {
       return false;
     }
+    return context.isAccessible(getUserPermissions(user));
+  }
 
-    List<Permission> allUserPermissions = properties.getRoles().stream()
+  private List<Permission> getUserPermissions(AuthenticatedUser user) {
+    return properties.getRoles().stream()
         .filter(filterRole(user))
         .flatMap(role -> role.getPermissions().stream())
         .toList();
-
-    return context.isAccessible(allUserPermissions);
   }
 
-  public Mono<AuthenticatedUser> getUser() {
+  public static Mono<AuthenticatedUser> getUser() {
     return ReactiveSecurityContextHolder.getContext()
         .map(SecurityContext::getAuthentication)
         .filter(authentication -> authentication.getPrincipal() instanceof RbacUser)
@@ -126,12 +126,7 @@ public class AccessControlService {
   }
 
   private boolean isClusterAccessible(String clusterName, AuthenticatedUser user) {
-    if (!rbacEnabled) {
-      return true;
-    }
-
     Assert.isTrue(StringUtils.isNotEmpty(clusterName), "cluster value is empty");
-
     return properties.getRoles()
         .stream()
         .filter(filterRole(user))
@@ -151,64 +146,46 @@ public class AccessControlService {
     }
     return getUser()
         .map(user -> topics.stream()
-            .filter(topic -> {
-                  var accessContext = AccessContext
-                      .builder()
-                      .cluster(clusterName)
-                      .topicActions(topic.getName(), TopicAction.VIEW)
-                      .build();
-                  return isAccessible(user, accessContext);
-                }
+            .filter(topic ->
+                isAccessible(
+                    user,
+                    AccessContext.builder()
+                        .cluster(clusterName)
+                        .topicActions(topic.getName(), TopicAction.VIEW)
+                        .build()
+                )
             ).toList());
   }
 
   public Mono<Boolean> isConsumerGroupAccessible(String groupId, String clusterName) {
-    if (!rbacEnabled) {
-      return Mono.just(true);
-    }
-
-    AccessContext accessContext = AccessContext
-        .builder()
-        .cluster(clusterName)
-        .consumerGroupActions(groupId, ConsumerGroupAction.VIEW)
-        .build();
-
-    return getUser().map(u -> isAccessible(u, accessContext));
+    return isAccessible(
+        AccessContext.builder()
+            .cluster(clusterName)
+            .consumerGroupActions(groupId, ConsumerGroupAction.VIEW)
+            .build()
+    );
   }
 
   public Mono<Boolean> isSchemaAccessible(String schema, String clusterName) {
-    if (!rbacEnabled) {
-      return Mono.just(true);
-    }
-
-    AccessContext accessContext = AccessContext
-        .builder()
-        .cluster(clusterName)
-        .schemaActions(schema, SchemaAction.VIEW)
-        .build();
-
-    return getUser().map(u -> isAccessible(u, accessContext));
+    return isAccessible(
+        AccessContext.builder()
+            .cluster(clusterName)
+            .schemaActions(schema, SchemaAction.VIEW)
+            .build()
+    );
   }
 
   public Mono<Boolean> isConnectAccessible(ConnectDTO dto, String clusterName) {
-    if (!rbacEnabled) {
-      return Mono.just(true);
-    }
     return isConnectAccessible(dto.getName(), clusterName);
   }
 
   public Mono<Boolean> isConnectAccessible(String connectName, String clusterName) {
-    if (!rbacEnabled) {
-      return Mono.just(true);
-    }
-
-    AccessContext accessContext = AccessContext
-        .builder()
-        .cluster(clusterName)
-        .connectActions(connectName, ConnectAction.VIEW)
-        .build();
-
-    return getUser().map(u -> isAccessible(u, accessContext));
+    return isAccessible(
+        AccessContext.builder()
+            .cluster(clusterName)
+            .connectActions(connectName, ConnectAction.VIEW)
+            .build()
+    );
   }
 
   public Set<ProviderAuthorityExtractor> getOauthExtractors() {