From d3a9e251cd6d9bf0cec1dd0ae1caede1be0cb71b Mon Sep 17 00:00:00 2001 From: "peng.jianhua" Date: Fri, 15 Sep 2017 16:16:39 +0800 Subject: [PATCH 1/1] KYLIN-2703 kylin supports managing access rights for project and cube through apache ranger. --- .../kylin/metadata/project/ProjectManager.java | 9 ++++ .../org/apache/kylin/rest/constant/Constant.java | 5 ++ .../kylin/rest/controller/AccessController.java | 21 +++++++- .../kylin/rest/security/ExternalAclProvider.java | 3 +- .../rest/security/KylinAclPermissionEvaluator.java | 17 ++----- .../apache/kylin/rest/util/AclPermissionUtil.java | 58 ++++++++++++++++++++++ webapp/app/js/services/kylinProperties.js | 2 +- webapp/app/partials/cubes/cube_detail.html | 2 +- webapp/app/partials/projects/project_detail.html | 2 +- 9 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 server-base/src/main/java/org/apache/kylin/rest/util/AclPermissionUtil.java diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java index df5450cf8..baf329558 100644 --- a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java +++ b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java @@ -447,6 +447,15 @@ public class ProjectManager { return projects; } + public ProjectInstance getProjectByUuid(String uuid) { + Collection copy = new ArrayList(projectMap.values()); + for (ProjectInstance project : copy) { + if (uuid.equals(project.getUuid())) + return project; + } + return null; + } + public ExternalFilterDesc getExternalFilterDesc(String project, String extFilter) { return l2Cache.getExternalFilterDesc(project, extFilter); } diff --git a/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java b/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java index 05adef13e..a1ce32e67 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java +++ b/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java @@ -47,4 +47,9 @@ public class Constant { public final static String SERVER_MODE_QUERY = "query"; public final static String SERVER_MODE_JOB = "job"; public final static String SERVER_MODE_ALL = "all"; + + public final static String CUBE_ADMIN = "CUBE ADMIN"; + public final static String CUBE_EDIT = "CUBE EDIT"; + public final static String CUBE_OPERATION = "CUBE OPERATION"; + public final static String CUBE_QUERY = "CUBE QUERY"; } diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java index 81153c285..0fd27a504 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java +++ b/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java @@ -30,12 +30,15 @@ import org.apache.kylin.rest.security.AclPermission; import org.apache.kylin.rest.security.AclPermissionFactory; import org.apache.kylin.rest.security.ExternalAclProvider; import org.apache.kylin.rest.service.AccessService; +import org.apache.kylin.rest.service.UserService; +import org.apache.kylin.rest.util.AclPermissionUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.acls.domain.PrincipalSid; import org.springframework.security.acls.model.Acl; import org.springframework.security.acls.model.Permission; import org.springframework.security.acls.model.Sid; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -55,6 +58,10 @@ public class AccessController extends BasicController { @Qualifier("accessService") private AccessService accessService; + @Autowired + @Qualifier("userService") + private UserService userService; + /** * Get access entry list of a domain object * @@ -64,9 +71,9 @@ public class AccessController extends BasicController { */ @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.GET }, produces = { "application/json" }) @ResponseBody - public List getAccessEntities(@PathVariable String type, @PathVariable String uuid) { + public List getAccessEntities(@PathVariable String type, @PathVariable String uuid) throws IOException { ExternalAclProvider eap = ExternalAclProvider.getInstance(); - + if (eap != null) { List ret = new ArrayList<>(); List> acl = eap.getAcl(type, uuid); @@ -75,6 +82,16 @@ public class AccessController extends BasicController { PrincipalSid sid = new PrincipalSid(p.getFirst()); ret.add(new AccessEntryResponse(null, sid, p.getSecond(), true)); } + } else { + for (UserDetails user : userService.listUsers()) { + PrincipalSid sid = new PrincipalSid(user.getUsername()); + List authorities = AclPermissionUtil.transformAuthorities(user.getAuthorities()); + for (Permission p : AclPermissionFactory.getPermissions()) { + if (eap.checkPermission(user.getUsername(), authorities, type, uuid, p)) { + ret.add(new AccessEntryResponse(null, sid, p, true)); + } + } + } } return ret; } else { diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/ExternalAclProvider.java b/server-base/src/main/java/org/apache/kylin/rest/security/ExternalAclProvider.java index b748c2766..4d66d7222 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/security/ExternalAclProvider.java +++ b/server-base/src/main/java/org/apache/kylin/rest/security/ExternalAclProvider.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.kylin.common.KylinConfig; import org.apache.kylin.common.util.ClassUtil; import org.apache.kylin.common.util.Pair; +import org.springframework.security.acls.model.Permission; /** */ @@ -64,7 +65,7 @@ abstract public class ExternalAclProvider { * @return true if has permission */ abstract public boolean checkPermission(String user, List userRoles, // - String entityType, String entityUuid, AclPermission permission); + String entityType, String entityUuid, Permission permission); /** * Returns all granted permissions on specified entity. diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/KylinAclPermissionEvaluator.java b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAclPermissionEvaluator.java index 1cdd5117c..b67753758 100644 --- a/server-base/src/main/java/org/apache/kylin/rest/security/KylinAclPermissionEvaluator.java +++ b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAclPermissionEvaluator.java @@ -19,17 +19,16 @@ package org.apache.kylin.rest.security; import java.io.Serializable; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.kylin.common.persistence.AclEntity; import org.apache.kylin.rest.service.AclService; +import org.apache.kylin.rest.util.AclPermissionUtil; import org.springframework.security.acls.AclPermissionEvaluator; import org.springframework.security.acls.domain.PermissionFactory; import org.springframework.security.acls.model.Permission; import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; public class KylinAclPermissionEvaluator extends AclPermissionEvaluator { @@ -59,11 +58,11 @@ public class KylinAclPermissionEvaluator extends AclPermissionEvaluator { String entityUuid, Object permission) { String currentUser = authentication.getName(); - List authorities = getAuthorities(authentication); + List authorities = AclPermissionUtil.transformAuthorities(authentication.getAuthorities()); List kylinPermissions = resolveKylinPermission(permission); for (Permission p : kylinPermissions) { - if (eap.checkPermission(currentUser, authorities, entityType, entityUuid, (AclPermission) p)) + if (eap.checkPermission(currentUser, authorities, entityType, entityUuid, p)) return true; } return false; @@ -100,16 +99,6 @@ public class KylinAclPermissionEvaluator extends AclPermissionEvaluator { throw new IllegalArgumentException("Unsupported permission: " + permission); } - private List getAuthorities(Authentication authentication) { - List authorities = new ArrayList(); - for (GrantedAuthority auth : authentication.getAuthorities()) { - if (!authorities.contains(auth.getAuthority())) { - authorities.add(auth.getAuthority()); - } - } - return authorities; - } - @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/AclPermissionUtil.java b/server-base/src/main/java/org/apache/kylin/rest/util/AclPermissionUtil.java new file mode 100644 index 000000000..1e6767765 --- /dev/null +++ b/server-base/src/main/java/org/apache/kylin/rest/util/AclPermissionUtil.java @@ -0,0 +1,58 @@ +/* + * 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.kylin.rest.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.kylin.rest.constant.Constant; +import org.apache.kylin.rest.security.AclPermission; +import org.springframework.security.acls.model.Permission; +import org.springframework.security.core.GrantedAuthority; + +public class AclPermissionUtil { + + public static String transformPermission(Permission p) { + String permString = null; + if (AclPermission.ADMINISTRATION.equals(p)) { + permString = Constant.CUBE_ADMIN; + } else if (AclPermission.MANAGEMENT.equals(p)) { + permString = Constant.CUBE_EDIT; + } else if (AclPermission.OPERATION.equals(p)) { + permString = Constant.CUBE_OPERATION; + } else if (AclPermission.READ.equals(p)) { + permString = Constant.CUBE_QUERY; + } else { + permString = p.getPattern(); + } + return permString; + } + + public static List transformAuthorities(Collection authorities) { + List ret = new ArrayList(); + for (GrantedAuthority auth : authorities) { + if (!authorities.contains(auth.getAuthority())) { + ret.add(auth.getAuthority()); + } + } + return ret; + } + +} diff --git a/webapp/app/js/services/kylinProperties.js b/webapp/app/js/services/kylinProperties.js index 04e5cefcd..a2af4ede7 100644 --- a/webapp/app/js/services/kylinProperties.js +++ b/webapp/app/js/services/kylinProperties.js @@ -107,7 +107,7 @@ KylinApp.service('kylinConfig', function (AdminService, $log) { } } - this.isRangerAclEnabled = function() { + this.isExternalAclEnabled = function() { var status = this.getProperty("kylin.server.external-acl-provider").trim(); if (status == '') { return false; diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html index 06f66f860..51f7dee97 100755 --- a/webapp/app/partials/cubes/cube_detail.html +++ b/webapp/app/partials/cubes/cube_detail.html @@ -30,7 +30,7 @@ JSON(Cube)
  • + ng-if="!kylinConfig.isExternalAclEnabled()"> Access
  • Cubes
  • + ng-if="!kylinConfig.isExternalAclEnabled()"> Access
  • -- 2.11.0.windows.1