ramackri commented on code in PR #1000:
URL: https://github.com/apache/ranger/pull/1000#discussion_r3377984394


##########
security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java:
##########
@@ -314,24 +313,31 @@ public RangerRoleList getRolesForUser(SearchFilter 
filter, RangerRoleList ranger
         List<RangerRole> roles;
         UserSessionBase  userSession = ContextUtil.getCurrentUserSession();
 
-        if (userSession != null && userSession.getUserRoleList().size() == 1 
&& userSession.getUserRoleList().contains(RangerConstants.ROLE_USER) && 
userSession.getLoginId() != null) {
-            VXUser       loggedInVXUser = 
xUserService.getXUserByUserName(userSession.getLoginId());
-            List<XXRole> xxRoles        = 
daoMgr.getXXRole().findByUserId(loggedInVXUser.getId());
+        // Plain ROLE_USER only; config super-users see all roles.
+        if (userSession != null && userSession.isSingleRoleUserSession()

Review Comment:
   Done — consolidated the multi-line statement in `RoleDBStore` (commit 
6839362f0).



##########
security-admin/src/main/java/org/apache/ranger/biz/SessionMgr.java:
##########
@@ -556,6 +566,50 @@ private void setUserRoles(UserSessionBase userSession) {
             userSession.setUserAdmin(false);
         }
 
+        applyConfigSuperUserSessionFlags(userSession);
+
+        if (userSession.isSuperUser()) {
+            strRoleList = 
RangerSuperUserConfig.mergeConfigSuperUserRoles(strRoleList, true);
+        }
+
         userSession.setUserRoleList(strRoleList);
     }
+
+    /**
+     * Applies config super-user session flag ({@code superUser}) when login 
matches
+     * {@code ranger.admin.super.users} / super.groups.
+     */
+    private void applyConfigSuperUserSessionFlags(
+            final UserSessionBase userSession) {
+        if (userSession == null) {

Review Comment:
   Done — refactored `applyConfigSuperUserToSession()` to use a single 
`isSuperUser` local with one assignment path per branch, matching the structure 
you suggested (commit 6839362f0).



##########
security-admin/src/main/java/org/apache/ranger/common/RangerSuperUserConfig.java:
##########
@@ -0,0 +1,245 @@
+/*
+ * 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.ranger.common;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Configuration-based Ranger Admin super users and super groups.
+ * When {@code ranger.admin.super.users} or
+ * {@code ranger.admin.super.groups} are set, matching authenticated users
+ * receive full Ranger administrative privileges (system admin and key admin
+ * capabilities) without requiring corresponding roles in the Ranger database.
+ */
+public final class RangerSuperUserConfig {
+    private static volatile RangerSuperUserConfig instance;
+
+    private final boolean superUsersConfigured;
+    private final boolean superGroupsConfigured;
+    private final boolean enabled;
+
+    private RangerSuperUserConfig() {

Review Comment:
   Fixed in latest commit (0463bda0f) — `RangerSuperUserConfig` now parses 
`super.users` and `super.groups` into cached `Set<String>` at construction 
time. `isSuperUser()` uses `Set.contains()` with exact match; no per-call 
`PropertiesUtil` lookups.



##########
security-admin/src/main/java/org/apache/ranger/common/RangerSuperUserConfig.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * 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.ranger.common;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Configuration-based Ranger Admin superusers and super groups.
+ * When {@code ranger.admin.super.users} or
+ * {@code ranger.admin.super.groups} are set, matching authenticated users
+ * receive full Ranger administrative privileges (system admin and key admin
+ * capabilities) without requiring corresponding roles in the Ranger database.
+ */
+public final class RangerSuperUserConfig {
+    private static volatile RangerSuperUserConfig instance;
+
+    private final Set<String> superUsers;
+    private final Set<String> superUserGroups;
+    private final boolean     superUsersConfigured;
+    private final boolean     superGroupsConfigured;
+    private final boolean     enabled;
+
+    private RangerSuperUserConfig() {
+        superUsers = parsePropertyValues(
+                PropertiesUtil.getPropertyStringList(
+                        RangerConstants.RANGER_ADMIN_SUPER_USERS));
+        superUserGroups = parsePropertyValues(
+                PropertiesUtil.getPropertyStringList(
+                        RangerConstants.RANGER_ADMIN_SUPER_GROUPS));
+        superUsersConfigured  = !superUsers.isEmpty();
+        superGroupsConfigured = !superUserGroups.isEmpty();
+        enabled               = superUsersConfigured || superGroupsConfigured;
+    }
+
+    /**
+     * Clears cached config snapshot. For unit tests only after
+     * {@link PropertiesUtil} properties change.
+     */
+    public static synchronized void resetForTests() {
+        instance = null;
+    }
+
+    /**
+     * @return true when {@code ranger.admin.super.users} or
+     *         {@code ranger.admin.super.groups} has at least one non-blank
+     *         entry
+     */
+    public static boolean isEnabled() {
+        return getInstance().enabled;
+    }
+
+    /**
+     * @return true when {@code ranger.admin.super.groups} has at least one
+     *         non-blank entry
+     */
+    public static boolean isSuperGroupsConfigured() {
+        return getInstance().superGroupsConfigured;
+    }
+
+    /**
+     * @param userName authenticated username
+     * @return true when userName matches configured superusers
+     */
+    public static boolean isSuperUser(final String userName) {
+        final boolean isSuperUser;
+        RangerSuperUserConfig cfg = getInstance();
+
+        if (StringUtils.isBlank(userName) || !cfg.enabled) {
+            isSuperUser = false;
+        } else if (cfg.superUsersConfigured && cfg.matchesUser(userName)) {
+            isSuperUser = true;
+        } else {
+            isSuperUser = false;
+        }
+
+        return isSuperUser;
+    }
+
+    /**
+     * @param userName authenticated user name
+     * @param userGroups group names from Ranger user store
+     * @return true when userName or groups match configured super users/groups
+     */
+    public static boolean isSuperUser(final String userName, final Set<String> 
userGroups) {
+        final boolean isSuperUser;
+        RangerSuperUserConfig cfg = getInstance();
+        if (StringUtils.isBlank(userName) || !cfg.enabled) {
+            isSuperUser = false;
+        } else if (cfg.superUsersConfigured && cfg.matchesUser(userName)) {
+            isSuperUser = true;
+        } else {
+            isSuperUser = cfg.superGroupsConfigured && 
cfg.matchesGroups(userGroups);
+        }
+
+        return isSuperUser;
+    }
+
+    /**
+     * Merges config super-user admin roles with existing portal roles.
+     * Used for Spring Security authentication and session role lists.
+     *
+     * @param existingRoles DB portal roles (may be null)
+     * @param includeRoleUser when true, adds {@code ROLE_USER} (session lists)
+     * @return merged role list with stable ordering
+     */
+    public static List<String> mergeConfigSuperUserRoles(final 
Collection<String> existingRoles, final boolean includeRoleUser) {
+        LinkedHashSet<String> merged = new LinkedHashSet<>();
+
+        merged.add(RangerConstants.ROLE_SYS_ADMIN);
+        merged.add(RangerConstants.ROLE_KEY_ADMIN);
+
+        if (includeRoleUser) {
+            merged.add(RangerConstants.ROLE_USER);
+        }
+
+        if (existingRoles != null) {
+            merged.addAll(existingRoles);
+        }
+
+        return new ArrayList<>(merged);
+    }
+
+    /**
+     * Admin roles exposed on {@code GET /user/profile} for config super-users.
+     */
+    public static List<String> getConfigSuperUserProfileRoles() {
+        return mergeConfigSuperUserRoles(Collections.emptyList(), false);
+    }
+
+    private static Set<String> parsePropertyValues(final String[] values) {
+        Set<String> parsed = new HashSet<>();
+
+        if (values != null) {
+            for (String value : values) {
+                if (StringUtils.isNotBlank(value)) {
+                    parsed.add(value.trim());
+                }
+            }
+        }
+
+        return Collections.unmodifiableSet(parsed);
+    }
+
+    private static RangerSuperUserConfig getInstance() {
+        RangerSuperUserConfig cfg = instance;
+
+        if (cfg == null) {
+            synchronized (RangerSuperUserConfig.class) {
+                cfg = instance;
+                if (cfg == null) {
+                    cfg = new RangerSuperUserConfig();
+                    instance = cfg;
+                }
+            }
+        }
+
+        return cfg;
+    }
+
+    private boolean matchesUser(final String userName) {
+        final boolean matched;
+
+        if (StringUtils.isBlank(userName)) {
+            matched = false;
+        } else {
+            // Case-insensitive match; "*" wildcard is not handled by 
CollectionUtils.contains
+            boolean result = false;
+
+            for (String configuredUser : superUsers) {
+                if ("*".equals(configuredUser) || 
configuredUser.equalsIgnoreCase(userName)) {

Review Comment:
   Done (0463bda0f) — removed `*` wildcard support and `equalsIgnoreCase()` 
matching. User and group names now use exact `Set.contains()` / 
`CollectionUtils.containsAny()`, consistent with the rest of the codebase.



##########
security-admin/src/main/java/org/apache/ranger/common/RangerSuperUserConfig.java:
##########
@@ -0,0 +1,249 @@
+/*
+ * 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.ranger.common;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Configuration-based Ranger Admin superusers and super groups.
+ * When {@code ranger.admin.super.users} or
+ * {@code ranger.admin.super.groups} are set, matching authenticated users
+ * receive full Ranger administrative privileges (system admin and key admin
+ * capabilities) without requiring corresponding roles in the Ranger database.
+ */
+public final class RangerSuperUserConfig {
+    private static volatile RangerSuperUserConfig instance;
+
+    private final Set<String> superUsers;
+    private final Set<String> superUserGroups;
+    private final boolean     superUsersConfigured;
+    private final boolean     superGroupsConfigured;
+    private final boolean     enabled;
+
+    private RangerSuperUserConfig() {
+        superUsers = parsePropertyValues(
+                PropertiesUtil.getPropertyStringList(
+                        RangerConstants.RANGER_ADMIN_SUPER_USERS));
+        superUserGroups = parsePropertyValues(
+                PropertiesUtil.getPropertyStringList(
+                        RangerConstants.RANGER_ADMIN_SUPER_GROUPS));
+        superUsersConfigured  = !superUsers.isEmpty();
+        superGroupsConfigured = !superUserGroups.isEmpty();
+        enabled               = superUsersConfigured || superGroupsConfigured;
+    }
+
+    /**
+     * Clears cached config snapshot. For unit tests only after
+     * {@link PropertiesUtil} properties change.
+     */
+    public static synchronized void resetForTests() {
+        instance = null;
+    }
+
+    /**
+     * @return true when {@code ranger.admin.super.users} or
+     *         {@code ranger.admin.super.groups} has at least one non-blank
+     *         entry
+     */
+    public static boolean isEnabled() {
+        return getInstance().enabled;
+    }
+
+    /**
+     * @return true when {@code ranger.admin.super.groups} has at least one
+     *         non-blank entry
+     */
+    public static boolean isSuperGroupsConfigured() {
+        return getInstance().superGroupsConfigured;
+    }
+
+    /**
+     * @param userName authenticated username
+     * @return true when userName matches configured superusers
+     */
+    public static boolean isSuperUser(final String userName) {
+        final boolean isSuperUser;
+        RangerSuperUserConfig cfg = getInstance();
+
+        if (StringUtils.isBlank(userName) || !cfg.enabled) {
+            isSuperUser = false;
+        } else if (cfg.superUsersConfigured && cfg.matchesUser(userName)) {
+            isSuperUser = true;
+        } else {
+            isSuperUser = false;
+        }
+
+        return isSuperUser;
+    }
+
+    /**
+     * @param userName authenticated user name
+     * @param userGroups group names from Ranger user store
+     * @return true when userName or groups match configured super users/groups
+     */
+    public static boolean isSuperUser(final String userName, final Set<String> 
userGroups) {
+        final boolean isSuperUser;
+        RangerSuperUserConfig cfg = getInstance();
+        if (StringUtils.isBlank(userName) || !cfg.enabled) {
+            isSuperUser = false;
+        } else if (cfg.superUsersConfigured && cfg.matchesUser(userName)) {
+            isSuperUser = true;
+        } else {
+            isSuperUser = cfg.superGroupsConfigured && 
cfg.matchesGroups(userGroups);
+        }
+
+        return isSuperUser;
+    }
+
+    /**
+     * Merges config super-user admin roles with existing portal roles.
+     * Used for Spring Security authentication and session role lists.
+     *
+     * @param existingRoles DB portal roles (may be null)
+     * @param includeRoleUser when true, adds {@code ROLE_USER} (session lists)
+     * @return merged role list with stable ordering
+     */
+    public static List<String> mergeConfigSuperUserRoles(final 
Collection<String> existingRoles, final boolean includeRoleUser) {
+        LinkedHashSet<String> merged = new LinkedHashSet<>();
+
+        merged.add(RangerConstants.ROLE_SYS_ADMIN);
+        merged.add(RangerConstants.ROLE_KEY_ADMIN);
+
+        if (includeRoleUser) {
+            merged.add(RangerConstants.ROLE_USER);
+        }
+
+        if (existingRoles != null) {
+            merged.addAll(existingRoles);
+        }
+
+        return new ArrayList<>(merged);
+    }
+
+    /**
+     * Admin roles exposed on {@code GET /user/profile} for config super-users.
+     */
+    public static List<String> getConfigSuperUserProfileRoles() {
+        return mergeConfigSuperUserRoles(Collections.emptyList(), false);
+    }
+
+    private static Set<String> parsePropertyValues(final String[] values) {
+        Set<String> parsed = new HashSet<>();
+
+        if (values != null) {
+            for (String value : values) {
+                if (StringUtils.isNotBlank(value)) {
+                    parsed.add(value.trim());
+                }
+            }
+        }
+
+        return Collections.unmodifiableSet(parsed);
+    }
+
+    private static RangerSuperUserConfig getInstance() {
+        RangerSuperUserConfig cfg = instance;
+
+        if (cfg == null) {
+            synchronized (RangerSuperUserConfig.class) {
+                cfg = instance;
+                if (cfg == null) {
+                    cfg = new RangerSuperUserConfig();
+                    instance = cfg;
+                }
+            }
+        }
+
+        return cfg;
+    }
+
+    private boolean matchesUser(final String userName) {
+        final boolean matched;
+
+        if (StringUtils.isBlank(userName)) {
+            matched = false;
+        } else {
+            // Case-insensitive match; "*" wildcard is not handled by 
CollectionUtils.contains
+            boolean result = false;
+
+            for (String configuredUser : superUsers) {
+                if ("*".equals(configuredUser) || 
configuredUser.equalsIgnoreCase(userName)) {
+                    result = true;
+                    break;
+                }
+            }
+
+            matched = result;
+        }
+
+        return matched;
+    }
+
+    private boolean matchesGroups(final Set<String> userGroups) {
+        final boolean matched;
+
+        if (CollectionUtils.isEmpty(userGroups)) {
+            matched = false;
+        } else {
+            // Case-insensitive match; GROUP_PUBLIC is not handled by 
CollectionUtils.containsAny
+            boolean result = false;
+
+            for (String configuredGroup : superUserGroups) {
+                if 
(RangerConstants.GROUP_PUBLIC.equalsIgnoreCase(configuredGroup) || 
containsGroupIgnoreCase(userGroups, configuredGroup)) {

Review Comment:
   Done (0463bda0f) — removed the special `public` group handling. Super-group 
matching is now a straight exact match against configured group names.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to