You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ni...@apache.org on 2019/08/22 00:34:56 UTC

[kylin] branch master updated: KYLIN-4139 Compatible old user security xml config when user upgrate new kylin version

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 2def3a4  KYLIN-4139 Compatible old user security xml config when user upgrate new kylin version
2def3a4 is described below

commit 2def3a4cf526151e07bcb3c97b48ace21b91d25d
Author: luguosheng1314 <55...@qq.com>
AuthorDate: Fri Aug 16 11:29:07 2019 +0800

    KYLIN-4139 Compatible old user security xml config when user upgrate new kylin version
---
 .../java/org/apache/kylin/common/KylinVersion.java |  6 +--
 .../kylin/rest/controller/UserController.java      | 13 -----
 .../kylin/rest/security/KylinUserManager.java      |  5 +-
 .../kylin/rest/service/KylinUserGroupService.java  | 32 ++++---------
 .../kylin/rest/service/KylinUserService.java       | 56 +++++++++++++++++++++-
 server/src/main/resources/kylinSecurity.xml        |  8 ++++
 .../rest/service/KylinUserGroupServiceTest.java    |  5 +-
 .../apache/kylin/rest/service/UserServiceTest.java |  2 +-
 8 files changed, 82 insertions(+), 45 deletions(-)

diff --git a/core-common/src/main/java/org/apache/kylin/common/KylinVersion.java b/core-common/src/main/java/org/apache/kylin/common/KylinVersion.java
index bbdb3a8..51c0674 100644
--- a/core-common/src/main/java/org/apache/kylin/common/KylinVersion.java
+++ b/core-common/src/main/java/org/apache/kylin/common/KylinVersion.java
@@ -88,14 +88,14 @@ public class KylinVersion implements Comparable {
         comp = this.internal - v.internal;
         if (comp != 0)
             return comp;
-        
+
         return (this.isSnapshot ? 0 : 1) - (v.isSnapshot ? 0 : 1);
     }
 
     /**
      * Require MANUAL updating kylin version per ANY upgrading.
      */
-    private static final KylinVersion CURRENT_KYLIN_VERSION = new KylinVersion("2.6.0.20500");
+    private static final KylinVersion CURRENT_KYLIN_VERSION = new KylinVersion("3.0.0.20500");
 
     private static final KylinVersion VERSION_200 = new KylinVersion("2.0.0");
 
@@ -131,7 +131,7 @@ public class KylinVersion implements Comparable {
     public static boolean isBefore200(String ver) {
         return new KylinVersion(ver).compareTo(VERSION_200) < 0;
     }
-    
+
     public static int compare(String v1, String v2) {
         return new KylinVersion(v1).compareTo(new KylinVersion(v2));
     }
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java
index d1ba18b..2ff53f2 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java
@@ -78,10 +78,6 @@ public class UserController extends BasicController {
 
     private static final SimpleGrantedAuthority ALL_USERS_AUTH = new SimpleGrantedAuthority(Constant.GROUP_ALL_USERS);
 
-    private static final String ADMIN = "ADMIN";
-    private static final String ANALYST = "ANALYST";
-    private static final String MODELER = "MODELER";
-    private static final String ADMIN_DEFAULT = "KYLIN";
     private static final String ACTIVE_PROFILES_NAME = "spring.profiles.active";
 
     @Autowired
@@ -135,15 +131,6 @@ public class UserController extends BasicController {
         passwordPattern = Pattern.compile("^(?=.*\\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*(){}|:\"<>?\\[\\];',./`]).{8,}$");
         bcryptPattern = Pattern.compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}");
         pwdEncoder = new BCryptPasswordEncoder();
-
-        List<ManagedUser> all = userService.listUsers();
-        logger.info("All {} users", all.size());
-        if (all.isEmpty() && "testing".equals(System.getProperty(ACTIVE_PROFILES_NAME))) {
-            create(ADMIN, new ManagedUser(ADMIN, ADMIN_DEFAULT, true, Constant.ROLE_ADMIN, Constant.GROUP_ALL_USERS));
-            create(ANALYST, new ManagedUser(ANALYST, ANALYST, true, Constant.GROUP_ALL_USERS));
-            create(MODELER, new ManagedUser(MODELER, MODELER, true, Constant.GROUP_ALL_USERS));
-        }
-
     }
 
     private void checkProfileEditAllowed() {
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/KylinUserManager.java b/server-base/src/main/java/org/apache/kylin/rest/security/KylinUserManager.java
index acbc008..afa78b0 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/security/KylinUserManager.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/KylinUserManager.java
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Locale;
 
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.ResourceStore;
@@ -120,7 +119,7 @@ public class KylinUserManager {
             if (exist != null) {
                 user.setLastModified(exist.getLastModified());
             }
-            user.setUsername(user.getUsername().toUpperCase(Locale.ROOT));
+            user.setUsername(user.getUsername());
             crud.save(user);
         } catch (IOException e) {
             throw new RuntimeException("Can not update user.", e);
@@ -129,7 +128,7 @@ public class KylinUserManager {
 
     public void delete(String username) {
         try (AutoReadWriteLock.AutoLock l = lock.lockForWrite()) {
-            crud.delete(username.toUpperCase(Locale.ROOT));
+            crud.delete(username);
         } catch (IOException e) {
             throw new RuntimeException("Can not delete user.", e);
         }
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserGroupService.java b/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserGroupService.java
index 033353f..8688f67 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserGroupService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserGroupService.java
@@ -18,8 +18,14 @@
 
 package org.apache.kylin.rest.service;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.persistence.JsonSerializer;
 import org.apache.kylin.common.persistence.ResourceStore;
@@ -34,16 +40,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
 
-import javax.annotation.PostConstruct;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 public class KylinUserGroupService extends UserGroupService {
     public static final Logger logger = LoggerFactory.getLogger(KylinUserGroupService.class);
@@ -58,18 +58,6 @@ public class KylinUserGroupService extends UserGroupService {
     @Autowired
     private AclEvaluate aclEvaluate;
 
-    List<String> getAllUserAuthorities() throws IOException {
-        List<String> all = new ArrayList<>();
-        for (UserDetails user : userService.listUsers()) {
-            for (GrantedAuthority auth : user.getAuthorities()) {
-                if (!all.contains(auth.getAuthority())) {
-                    all.add(auth.getAuthority());
-                }
-            }
-        }
-        return all;
-    }
-
     @Override
     public boolean exists(String name) throws IOException {
         return getUserGroup().getAllGroups().contains(name);
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserService.java b/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserService.java
index ea97118..53a611f 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/KylinUserService.java
@@ -27,6 +27,7 @@ import javax.annotation.PostConstruct;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.KylinVersion;
 import org.apache.kylin.common.persistence.JsonSerializer;
 import org.apache.kylin.common.persistence.ResourceStore;
 import org.apache.kylin.common.persistence.Serializer;
@@ -41,8 +42,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 
 import com.google.common.base.Preconditions;
 
@@ -58,6 +61,55 @@ public class KylinUserService implements UserService {
 
     public static final Serializer<ManagedUser> SERIALIZER = new JsonSerializer<>(ManagedUser.class);
 
+    private static final String ACTIVE_PROFILES_NAME = "spring.profiles.active";
+
+    private static final String ADMIN = "ADMIN";
+    private static final String MODELER = "MODELER";
+    private static final String ANALYST = "ANALYST";
+    private static final String ADMIN_DEFAULT = "KYLIN";
+    private BCryptPasswordEncoder pwdEncoder;
+    public List<User> configUsers;
+
+    public KylinUserService() {
+    }
+
+    public KylinUserService(List<User> users) throws IOException {
+        pwdEncoder = new BCryptPasswordEncoder();
+        synchronized (KylinUserService.class) {
+            if (!StringUtils.equals("testing", System.getProperty(ACTIVE_PROFILES_NAME))) {
+                return;
+            }
+            List<ManagedUser> all = listUsers();
+            configUsers = users;
+            // old security.xml config user pwd sync to user metadata
+            if (!configUsers.isEmpty()) {
+                for (User cuser : configUsers) {
+                    try {
+                        String username = cuser.getUsername();
+                        ManagedUser userDetail = (ManagedUser) loadUserByUsername(username);
+                        if (userDetail != null && new KylinVersion(userDetail.getVersion()).major < KylinVersion
+                                .getCurrentVersion().major) {
+                            updateUser(new ManagedUser(cuser.getUsername(), cuser.getPassword(), false,
+                                    cuser.getAuthorities()));
+                        }
+                    } catch (UsernameNotFoundException e) {
+                        // add new security user in security.xml if it is not in metadata
+                        createUser(new ManagedUser(cuser.getUsername(), cuser.getPassword(), false,
+                                cuser.getAuthorities()));
+                    }
+                }
+            }
+            // add default user info in metadata
+            if (all.isEmpty() && configUsers.isEmpty()) {
+                createUser(new ManagedUser(ADMIN, pwdEncoder.encode(ADMIN_DEFAULT), true, Constant.ROLE_ADMIN,
+                        Constant.GROUP_ALL_USERS));
+                createUser(new ManagedUser(ANALYST, pwdEncoder.encode(ANALYST), true, Constant.GROUP_ALL_USERS));
+                createUser(new ManagedUser(MODELER, pwdEncoder.encode(MODELER), true, Constant.GROUP_ALL_USERS));
+            }
+        }
+
+    }
+
     protected ResourceStore aclStore;
 
     private boolean evictCacheFlag = false;
@@ -88,6 +140,9 @@ public class KylinUserService implements UserService {
     public void updateUser(UserDetails user) {
         Preconditions.checkState(user instanceof ManagedUser, "User {} is not ManagedUser", user);
         ManagedUser managedUser = (ManagedUser) user;
+        if (!managedUser.getAuthorities().contains(new SimpleGrantedAuthority(Constant.GROUP_ALL_USERS))) {
+            managedUser.addAuthorities(Constant.GROUP_ALL_USERS);
+        }
         getKylinUserManager().update(managedUser);
         logger.trace("update user : {}", user.getUsername());
         setEvictCacheFlag(true);
@@ -98,7 +153,6 @@ public class KylinUserService implements UserService {
         if (userName.equalsIgnoreCase(SUPER_ADMIN)) {
             throw new InternalErrorException("User " + userName + " is not allowed to be deleted.");
         }
-
         getKylinUserManager().delete(userName);
         logger.trace("delete user : {}", userName);
         setEvictCacheFlag(true);
diff --git a/server/src/main/resources/kylinSecurity.xml b/server/src/main/resources/kylinSecurity.xml
index a7197ff..2befed5 100644
--- a/server/src/main/resources/kylinSecurity.xml
+++ b/server/src/main/resources/kylinSecurity.xml
@@ -203,6 +203,14 @@
                 <bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                     <property name="userDetailsService">
                         <bean class="org.apache.kylin.rest.service.KylinUserService">
+                            <constructor-arg>
+                                <util:list
+                                        value-type="org.springframework.security.core.userdetails.User">
+                                    <ref bean="adminUser"></ref>
+                                    <ref bean="modelerUser"></ref>
+                                    <ref bean="analystUser"></ref>
+                                </util:list>
+                            </constructor-arg>
                         </bean>
                     </property>
 
diff --git a/server/src/test/java/org/apache/kylin/rest/service/KylinUserGroupServiceTest.java b/server/src/test/java/org/apache/kylin/rest/service/KylinUserGroupServiceTest.java
index 5ca7f4e..0e37750 100644
--- a/server/src/test/java/org/apache/kylin/rest/service/KylinUserGroupServiceTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/service/KylinUserGroupServiceTest.java
@@ -36,7 +36,8 @@ public class KylinUserGroupServiceTest extends ServiceTestBase {
 
     @Test
     public void testGetAllUserAuthorities() throws IOException {
-        List<String> allUserAuthorities = userGroupService.getAllUserAuthorities();
-        Assert.assertEquals(Lists.newArrayList("ROLE_ADMIN", "ROLE_ANALYST", "ROLE_MODELER"), allUserAuthorities);
+        List<String> allUserAuthorities = userGroupService.getAllUserGroups();
+        Assert.assertEquals(Lists.newArrayList("ALL_USERS", "ROLE_ADMIN", "ROLE_ANALYST", "ROLE_MODELER"),
+                allUserAuthorities);
     }
 }
diff --git a/server/src/test/java/org/apache/kylin/rest/service/UserServiceTest.java b/server/src/test/java/org/apache/kylin/rest/service/UserServiceTest.java
index 284469c..179a38c 100644
--- a/server/src/test/java/org/apache/kylin/rest/service/UserServiceTest.java
+++ b/server/src/test/java/org/apache/kylin/rest/service/UserServiceTest.java
@@ -56,7 +56,7 @@ public class UserServiceTest extends ServiceTestBase {
         Assert.assertEquals("MODELER", ud.getUsername());
         Assert.assertEquals("PWD", ud.getPassword());
         Assert.assertEquals(Constant.ROLE_ADMIN, ud.getAuthorities().iterator().next().getAuthority());
-        Assert.assertEquals(1, ud.getAuthorities().size());
+        Assert.assertEquals(2, ud.getAuthorities().size());
 
     }