瀏覽代碼

RBAC integration added

iliax 2 年之前
父節點
當前提交
cb17449407

+ 48 - 9
kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AclsController.java

@@ -3,7 +3,10 @@ package com.provectus.kafka.ui.controller;
 import com.provectus.kafka.ui.api.AclsApi;
 import com.provectus.kafka.ui.api.AclsApi;
 import com.provectus.kafka.ui.mapper.ClusterMapper;
 import com.provectus.kafka.ui.mapper.ClusterMapper;
 import com.provectus.kafka.ui.model.KafkaAclDTO;
 import com.provectus.kafka.ui.model.KafkaAclDTO;
+import com.provectus.kafka.ui.model.rbac.AccessContext;
+import com.provectus.kafka.ui.model.rbac.permission.AclAction;
 import com.provectus.kafka.ui.service.acl.AclsService;
 import com.provectus.kafka.ui.service.acl.AclsService;
+import com.provectus.kafka.ui.service.rbac.AccessControlService;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import org.springframework.http.ResponseEntity;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
@@ -16,11 +19,19 @@ import reactor.core.publisher.Mono;
 public class AclsController extends AbstractController implements AclsApi {
 public class AclsController extends AbstractController implements AclsApi {
 
 
   private final AclsService aclsService;
   private final AclsService aclsService;
+  private final AccessControlService accessControlService;
 
 
   @Override
   @Override
   public Mono<ResponseEntity<Void>> createAcl(String clusterName, Mono<KafkaAclDTO> kafkaAclDto,
   public Mono<ResponseEntity<Void>> createAcl(String clusterName, Mono<KafkaAclDTO> kafkaAclDto,
                                               ServerWebExchange exchange) {
                                               ServerWebExchange exchange) {
-    return kafkaAclDto.map(ClusterMapper::toAclBinding)
+    AccessContext context = AccessContext.builder()
+        .cluster(clusterName)
+        .aclActions(AclAction.EDIT)
+        .build();
+
+    return accessControlService.validateAccess(context)
+        .then(kafkaAclDto)
+        .map(ClusterMapper::toAclBinding)
         .flatMap(binding -> aclsService.createAcl(getCluster(clusterName), binding))
         .flatMap(binding -> aclsService.createAcl(getCluster(clusterName), binding))
         .thenReturn(ResponseEntity.ok().build());
         .thenReturn(ResponseEntity.ok().build());
   }
   }
@@ -28,28 +39,56 @@ public class AclsController extends AbstractController implements AclsApi {
   @Override
   @Override
   public Mono<ResponseEntity<Void>> deleteAcl(String clusterName, Mono<KafkaAclDTO> kafkaAclDto,
   public Mono<ResponseEntity<Void>> deleteAcl(String clusterName, Mono<KafkaAclDTO> kafkaAclDto,
                                               ServerWebExchange exchange) {
                                               ServerWebExchange exchange) {
-    return kafkaAclDto.map(ClusterMapper::toAclBinding)
+    AccessContext context = AccessContext.builder()
+        .cluster(clusterName)
+        .aclActions(AclAction.EDIT)
+        .build();
+
+    return accessControlService.validateAccess(context)
+        .then(kafkaAclDto)
+        .map(ClusterMapper::toAclBinding)
         .flatMap(binding -> aclsService.deleteAcl(getCluster(clusterName), binding))
         .flatMap(binding -> aclsService.deleteAcl(getCluster(clusterName), binding))
         .thenReturn(ResponseEntity.ok().build());
         .thenReturn(ResponseEntity.ok().build());
   }
   }
 
 
   @Override
   @Override
   public Mono<ResponseEntity<Flux<KafkaAclDTO>>> listAcls(String clusterName, ServerWebExchange exchange) {
   public Mono<ResponseEntity<Flux<KafkaAclDTO>>> listAcls(String clusterName, ServerWebExchange exchange) {
-    return Mono.just(
-        ResponseEntity.ok(
-            aclsService.listAcls(getCluster(clusterName)).map(ClusterMapper::toKafkaAclDto)));
+    AccessContext context = AccessContext.builder()
+        .cluster(clusterName)
+        .aclActions(AclAction.VIEW)
+        .build();
+
+    return accessControlService.validateAccess(context).then(
+        Mono.just(
+            ResponseEntity.ok(
+                aclsService.listAcls(getCluster(clusterName)).map(ClusterMapper::toKafkaAclDto)))
+    );
   }
   }
 
 
   @Override
   @Override
   public Mono<ResponseEntity<String>> getAclAsCsv(String clusterName, ServerWebExchange exchange) {
   public Mono<ResponseEntity<String>> getAclAsCsv(String clusterName, ServerWebExchange exchange) {
-    return aclsService.getAclAsCsvString(getCluster(clusterName))
-        .map(ResponseEntity::ok)
-        .flatMap(Mono::just);
+    AccessContext context = AccessContext.builder()
+        .cluster(clusterName)
+        .aclActions(AclAction.VIEW)
+        .build();
+
+    return accessControlService.validateAccess(context).then(
+        aclsService.getAclAsCsvString(getCluster(clusterName))
+            .map(ResponseEntity::ok)
+            .flatMap(Mono::just)
+    );
   }
   }
 
 
   @Override
   @Override
   public Mono<ResponseEntity<Void>> syncAclsCsv(String clusterName, Mono<String> csvMono, ServerWebExchange exchange) {
   public Mono<ResponseEntity<Void>> syncAclsCsv(String clusterName, Mono<String> csvMono, ServerWebExchange exchange) {
-    return csvMono.flatMap(csv -> aclsService.syncAclWithAclCsv(getCluster(clusterName), csv))
+    AccessContext context = AccessContext.builder()
+        .cluster(clusterName)
+        .aclActions(AclAction.EDIT)
+        .build();
+
+    return accessControlService.validateAccess(context)
+        .then(csvMono)
+        .flatMap(csv -> aclsService.syncAclWithAclCsv(getCluster(clusterName), csv))
         .thenReturn(ResponseEntity.ok().build());
         .thenReturn(ResponseEntity.ok().build());
   }
   }
 }
 }

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

@@ -1,5 +1,6 @@
 package com.provectus.kafka.ui.model.rbac;
 package com.provectus.kafka.ui.model.rbac;
 
 
+import com.provectus.kafka.ui.model.rbac.permission.AclAction;
 import com.provectus.kafka.ui.model.rbac.permission.ClusterConfigAction;
 import com.provectus.kafka.ui.model.rbac.permission.ClusterConfigAction;
 import com.provectus.kafka.ui.model.rbac.permission.ConnectAction;
 import com.provectus.kafka.ui.model.rbac.permission.ConnectAction;
 import com.provectus.kafka.ui.model.rbac.permission.ConsumerGroupAction;
 import com.provectus.kafka.ui.model.rbac.permission.ConsumerGroupAction;
@@ -34,6 +35,8 @@ public class AccessContext {
 
 
   Collection<KsqlAction> ksqlActions;
   Collection<KsqlAction> ksqlActions;
 
 
+  Collection<AclAction> aclActions;
+
   public static AccessContextBuilder builder() {
   public static AccessContextBuilder builder() {
     return new AccessContextBuilder();
     return new AccessContextBuilder();
   }
   }
@@ -51,6 +54,7 @@ public class AccessContext {
     private String schema;
     private String schema;
     private Collection<SchemaAction> schemaActions = Collections.emptySet();
     private Collection<SchemaAction> schemaActions = Collections.emptySet();
     private Collection<KsqlAction> ksqlActions = Collections.emptySet();
     private Collection<KsqlAction> ksqlActions = Collections.emptySet();
+    private Collection<AclAction> aclActions = Collections.emptySet();
 
 
     private AccessContextBuilder() {
     private AccessContextBuilder() {
     }
     }
@@ -121,6 +125,12 @@ public class AccessContext {
       return this;
       return this;
     }
     }
 
 
+    public AccessContextBuilder aclActions(AclAction... actions) {
+      Assert.isTrue(actions.length > 0, "actions not present");
+      this.aclActions = List.of(actions);
+      return this;
+    }
+
     public AccessContext build() {
     public AccessContext build() {
       return new AccessContext(cluster, clusterConfigActions,
       return new AccessContext(cluster, clusterConfigActions,
           topic, topicActions,
           topic, topicActions,
@@ -128,7 +138,7 @@ public class AccessContext {
           connect, connectActions,
           connect, connectActions,
           connector,
           connector,
           schema, schemaActions,
           schema, schemaActions,
-          ksqlActions);
+          ksqlActions, aclActions);
     }
     }
   }
   }
 }
 }

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

@@ -10,7 +10,8 @@ public enum Resource {
   CONSUMER,
   CONSUMER,
   SCHEMA,
   SCHEMA,
   CONNECT,
   CONNECT,
-  KSQL;
+  KSQL,
+  ACL;
 
 
   @Nullable
   @Nullable
   public static Resource fromString(String name) {
   public static Resource fromString(String name) {

+ 15 - 0
kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/rbac/permission/AclAction.java

@@ -0,0 +1,15 @@
+package com.provectus.kafka.ui.model.rbac.permission;
+
+import org.apache.commons.lang3.EnumUtils;
+import org.jetbrains.annotations.Nullable;
+
+public enum AclAction implements PermissibleAction {
+
+  VIEW,
+  EDIT;
+
+  @Nullable
+  public static AclAction fromString(String name) {
+    return EnumUtils.getEnum(AclAction.class, name);
+  }
+}

+ 1 - 0
kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml

@@ -3316,6 +3316,7 @@ components:
         - SCHEMA
         - SCHEMA
         - CONNECT
         - CONNECT
         - KSQL
         - KSQL
+        - ACL
 
 
     KafkaAcl:
     KafkaAcl:
       type: object
       type: object