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

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


The following commit(s) were added to refs/heads/master by this push:
     new f056eae1f RANGER-5008:Handle creation of federated user in Ranger
f056eae1f is described below

commit f056eae1fda73c17e4c5332160144829eb7be949
Author: Ramesh Mani <[email protected]>
AuthorDate: Sun Dec 8 19:54:39 2024 -0800

    RANGER-5008:Handle creation of federated user in Ranger
---
 .../apache/ranger/plugin/util/PasswordUtils.java   | 118 +++++++++++++++++++++
 .../main/java/org/apache/ranger/biz/UserMgr.java   |   7 +-
 .../main/java/org/apache/ranger/biz/XUserMgr.java  |  16 +++
 .../java/org/apache/ranger/biz/TestXUserMgr.java   |  80 ++++++++++++++
 4 files changed, 218 insertions(+), 3 deletions(-)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
index 546412b53..6cd4ee044 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/PasswordUtils.java
@@ -19,6 +19,8 @@ package org.apache.ranger.plugin.util;
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import javax.crypto.Cipher;
@@ -229,4 +231,120 @@ public class PasswordUtils {
                }
                return decryptedPwd;
        }
+
+       /* Password Generator */
+       public static final class PasswordGenerator {
+               private static final String LOWER = 
"abcdefghijklmnopqrstuvwxyz";
+               private static final String UPPER = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+               private static final String DIGITS = "0123456789";
+               private static final String SYMBOLS = "!@#$%&*()_+-=[]|,./?><";
+               private final boolean useLower;
+               private final boolean useUpper;
+               private final boolean useDigits;
+               private final boolean useSymbols;
+
+               private PasswordGenerator(PasswordGeneratorBuilder builder) {
+                       this.useLower = builder.useLower;
+                       this.useUpper = builder.useUpper;
+                       this.useDigits = builder.useDigits;
+                       this.useSymbols = builder.useSymbols;
+               }
+
+               public static class PasswordGeneratorBuilder {
+                       private boolean useLower;
+                       private boolean useUpper;
+                       private boolean useDigits;
+                       private boolean useSymbols;
+
+                       public PasswordGeneratorBuilder() {
+                               this.useLower = false;
+                               this.useUpper = false;
+                               this.useDigits = false;
+                               this.useSymbols = false;
+                       }
+
+                       /**
+                        * @param useLower true in case you would like to 
include lowercase
+                        *                 characters (abc...xyz). Default 
false.
+                        * @return the builder for chaining.
+                        */
+                       public PasswordGeneratorBuilder useLower(boolean 
useLower) {
+                               this.useLower = useLower;
+                               return this;
+                       }
+
+                       /**
+                        * @param useUpper true in case you would like to 
include uppercase
+                        *                 characters (ABC...XYZ). Default 
false.
+                        * @return the builder for chaining.
+                        */
+                       public PasswordGeneratorBuilder useUpper(boolean 
useUpper) {
+                               this.useUpper = useUpper;
+                               return this;
+                       }
+
+                       /**
+                        * @param useDigits true in case you would like to 
include digit
+                        *                  characters (123...). Default false.
+                        * @return the builder for chaining.
+                        */
+                       public PasswordGeneratorBuilder useDigits(boolean 
useDigits) {
+                               this.useDigits = useDigits;
+                               return this;
+                       }
+
+                       /**
+                        * @param useSymbols true in case you would like to 
include
+                        *                   punctuation characters (!@#...). 
Default false.
+                        * @return the builder for chaining.
+                        */
+                       public PasswordGeneratorBuilder useSymbols(boolean 
useSymbols) {
+                               this.useSymbols = useSymbols;
+                               return this;
+                       }
+
+                       /**
+                        * Get an object to use.
+                        *
+                        * @return the {@link PasswordGenerator}
+                        * object.
+                        */
+                       public PasswordGenerator build() {
+                               return new PasswordGenerator(this);
+                       }
+               }
+
+               /**
+                * @param length the length of the password you would like to 
generate.
+                * @return a password that uses the categories you define when 
constructing
+                * the object with a probability.
+                */
+               public String generate(int length) {
+                       StringBuilder password = new StringBuilder(length);
+                       SecureRandom secureRandom = new SecureRandom();
+
+                       List<String> charCategories = new ArrayList<>(4);
+                       if (useLower) {
+                               charCategories.add(LOWER);
+                       }
+                       if (useUpper) {
+                               charCategories.add(UPPER);
+                       }
+                       if (useDigits) {
+                               charCategories.add(DIGITS);
+                       }
+                       if (useSymbols) {
+                               charCategories.add(SYMBOLS);
+                       }
+
+                       // Build the password.
+                       for (int i = 0; i < length; i++) {
+                               int    idxCatagory  = (i < 
charCategories.size()) ? i : secureRandom.nextInt(charCategories.size());
+                               String charCategory = 
charCategories.get(idxCatagory);
+                               int position = 
secureRandom.nextInt(charCategory.length());
+                               password.append(charCategory.charAt(position));
+                       }
+                       return new String(password);
+               }
+       }
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java 
b/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java
index 07119dee3..f19c04994 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java
@@ -1068,9 +1068,10 @@ public class UserMgr {
        }
 
        public VXPortalUser createDefaultAccountUser(VXPortalUser userProfile) {
-               if (userProfile.getPassword() == null
-                               || userProfile.getPassword().trim().isEmpty()) {
-                       
userProfile.setUserSource(RangerCommonEnums.USER_EXTERNAL);
+               if (userProfile.getUserSource() != 
RangerCommonEnums.USER_FEDERATED) {
+                       if (StringUtils.isBlank(userProfile.getPassword())) {
+                               
userProfile.setUserSource(RangerCommonEnums.USER_EXTERNAL);
+                       }
                }
                // access control
                checkAdminAccess();
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java 
b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
index cec829361..035070474 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
@@ -50,6 +50,7 @@ import org.apache.ranger.plugin.model.RangerPrincipal;
 import org.apache.ranger.plugin.model.UserInfo;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.util.RangerUserStore;
+import org.apache.ranger.plugin.util.PasswordUtils.PasswordGenerator;
 import org.apache.ranger.service.*;
 import org.apache.ranger.ugsyncutil.model.GroupUserInfo;
 import org.apache.ranger.ugsyncutil.model.UsersGroupRoleAssignments;
@@ -110,6 +111,7 @@ public class XUserMgr extends XUserMgrBase {
        private static final String USER = "User";
        private static final String GROUP = "Group";
        private static final int MAX_DB_TRANSACTION_RETRIES = 5;
+       private static final int PASSWORD_LENGTH = 16;
 
        @Autowired
        RangerBizUtil msBizUtil;
@@ -187,6 +189,20 @@ public class XUserMgr extends XUserMgrBase {
        public VXUser createXUser(VXUser vXUser) {
                checkAdminAccess();
                xaBizUtil.blockAuditorRoleUser();
+
+               if (vXUser.getUserSource() == RangerCommonEnums.USER_FEDERATED) 
{
+                       if (StringUtils.isEmpty(vXUser.getPassword())) {
+                               PasswordGenerator passwordGenerator = new 
PasswordGenerator.PasswordGeneratorBuilder()
+                                               .useLower(true)
+                                               .useUpper(true)
+                                               .useDigits(true)
+                                               .useSymbols(true)
+                                               .build();
+                               String passWd = 
passwordGenerator.generate(PASSWORD_LENGTH);
+                               vXUser.setPassword(passWd);
+                       }
+               }
+
                validatePassword(vXUser);
                String userName = vXUser.getName();
                String firstName = vXUser.getFirstName();
diff --git 
a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java 
b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
index 647891ef3..2da5d3cd8 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
@@ -278,6 +278,23 @@ public class TestXUserMgr {
                return vxUser;
        }
 
+       private VXUser vxUserFederated() {
+               Collection<String> userRoleList = new ArrayList<String>();
+               userRoleList.add("ROLE_USER");
+               Collection<String> groupNameList = new ArrayList<String>();
+               groupNameList.add(groupName);
+               VXUser vxUser = new VXUser();
+               vxUser.setId(userId);
+               vxUser.setDescription("group test working");
+               vxUser.setName(userLoginID);
+               vxUser.setUserRoleList(userRoleList);
+               vxUser.setGroupNameList(groupNameList);
+               vxUser.setPassword(null);
+               vxUser.setEmailAddress("[email protected]");
+               vxUser.setUserSource(RangerCommonEnums.USER_FEDERATED);
+               return vxUser;
+       }
+
        private XXUser xxUser(VXUser vxUser) {
                XXUser xXUser = new XXUser();
                xXUser.setId(userId);
@@ -4655,4 +4672,67 @@ public class TestXUserMgr {
                Assert.assertNotNull(createdXUser);
                Assert.assertEquals(createdXUser.getName(), vXUser.getName());
        }
+
+       @Test
+       public void test01CreateXUser_federated() {
+               destroySession();
+               setup();
+               VXUser vxUser = vxUserFederated();
+               vxUser.setFirstName("user12");
+               vxUser.setLastName("test12");
+               Collection<Long> groupIdList = new ArrayList<Long>();
+               groupIdList.add(userId);
+               vxUser.setGroupIdList(groupIdList);
+               VXGroup vxGroup = vxGroup();
+               vxGroup.setName("user12Grp");
+               VXGroupUser vXGroupUser = new VXGroupUser();
+               vXGroupUser.setParentGroupId(userId);
+               vXGroupUser.setUserId(userId);
+               vXGroupUser.setName(vxGroup.getName());
+               
Mockito.when(xGroupService.readResource(userId)).thenReturn(vxGroup);
+               Mockito.when(xGroupUserService.createResource((VXGroupUser) 
Mockito.any())).thenReturn(vXGroupUser);
+               ArrayList<String> userRoleListVXPortaUser = getRoleList();
+               VXPortalUser vXPortalUser = new VXPortalUser();
+               vXPortalUser.setUserRoleList(userRoleListVXPortaUser);
+               
Mockito.when(xUserService.createResource(vxUser)).thenReturn(vxUser);
+               XXModuleDefDao value = Mockito.mock(XXModuleDefDao.class);
+               Mockito.when(daoManager.getXXModuleDef()).thenReturn(value);
+               Mockito.when(userMgr.createDefaultAccountUser((VXPortalUser) 
Mockito.any())).thenReturn(vXPortalUser);
+               
Mockito.when(stringUtil.validateEmail("[email protected]")).thenReturn(true);
+               VXUser dbUser = xUserMgr.createXUser(vxUser);
+               Assert.assertNotNull(dbUser);
+               userId = dbUser.getId();
+               Assert.assertEquals(userId, dbUser.getId());
+               Assert.assertEquals(dbUser.getDescription(), 
vxUser.getDescription());
+               Assert.assertEquals(dbUser.getName(), vxUser.getName());
+               Assert.assertEquals(dbUser.getUserRoleList(), 
vxUser.getUserRoleList());
+               Assert.assertEquals(dbUser.getGroupNameList(),
+                               vxUser.getGroupNameList());
+               Assert.assertNotNull(dbUser.getPassword());
+               Assert.assertEquals(dbUser.getUserSource(), 
RangerCommonEnums.USER_FEDERATED);
+               Mockito.verify(xUserService).createResource(vxUser);
+               
Mockito.when(xUserService.readResourceWithOutLogin(userId)).thenReturn(vxUser);
+
+               VXUser loggedInUser = vxUser();
+               List<String> loggedInUserRole = new ArrayList<String>();
+               loggedInUserRole.add(RangerConstants.ROLE_ADMIN);
+               loggedInUser.setId(8L);
+               loggedInUser.setName("testuser");
+               loggedInUser.setUserRoleList(loggedInUserRole);
+               
Mockito.when(xUserService.getXUserByUserName("admin")).thenReturn(loggedInUser);
+               
Mockito.when(restErrorUtil.createRESTException(HttpServletResponse.SC_FORBIDDEN,
 "Logged-In user is not allowed to access requested user data", 
true)).thenThrow(new WebApplicationException());
+               thrown.expect(WebApplicationException.class);
+               VXUser dbvxUser = xUserMgr.getXUser(userId);
+               Mockito.verify(userMgr).createDefaultAccountUser((VXPortalUser) 
Mockito.any());
+               Assert.assertNotNull(dbvxUser);
+               Assert.assertEquals(userId, dbvxUser.getId());
+               Assert.assertEquals(dbvxUser.getDescription(), 
vxUser.getDescription());
+               Assert.assertEquals(dbvxUser.getName(), vxUser.getName());
+               
Assert.assertEquals(dbvxUser.getUserRoleList(),vxUser.getUserRoleList());
+               
Assert.assertEquals(dbvxUser.getGroupIdList(),vxUser.getGroupIdList());
+               
Assert.assertEquals(dbvxUser.getGroupNameList(),vxUser.getGroupNameList());
+               Assert.assertNotNull(dbvxUser.getPassword());
+               Assert.assertEquals(dbvxUser.getUserSource(), 
RangerCommonEnums.USER_FEDERATED);
+               Mockito.verify(xUserService).readResourceWithOutLogin(userId);
+       }
 }

Reply via email to