Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KARAF-5014: consider first group role in users.properties and ignore empty roles #1863

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@
# with the name "karaf"..
#
#karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh
_g_\:admingroup = admin,manager,viewer,systembundles,ssh
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
# The user guide describes how to generate/update the key.
#
#karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh
_g_\:admingroup = admin,manager,viewer,systembundles,ssh
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
# with the name "karaf".
#
#karaf = karaf,_g_:admingroup
#_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh
#_g_\:admingroup = admin,manager,viewer,systembundles,ssh
2 changes: 1 addition & 1 deletion client/src/test/resources/etc1/users.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
################################################################################

karaf = karaf,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles
_g_\:admingroup = admin,manager,viewer,systembundles
2 changes: 1 addition & 1 deletion client/src/test/resources/etc2/users.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#
################################################################################

_g_\:admingroup = group,admin,manager,viewer,systembundles
_g_\:admingroup = admin,manager,viewer,systembundles
test = admin,_g_:admingroup
admin = admin,_g_:admingroup
karaf = karaf,_g_:admingroup
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
# with the name "karaf".
#
karaf = karaf,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh
_g_\:admingroup = admin,manager,viewer,systembundles,ssh
2 changes: 1 addition & 1 deletion itests/test/src/test/resources/etc/users.properties
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
# with the name "karaf".
#
karaf = karaf,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh
_g_\:admingroup = admin,manager,viewer,systembundles,ssh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
*/
package org.apache.karaf.jaas.modules;

import org.apache.karaf.jaas.boot.principal.RolePrincipal;
import java.security.Principal;
import java.util.Map;
import java.util.Set;

public final class JAASUtils {

Expand All @@ -30,4 +33,20 @@ public static String getString(Map<String, ?> options, String key) {
return (String)val;
}

}
/**
* Determines the starting index of role and group definitions for a given key in a file-based login module.
* @param name the property key to evaluate, representing a group or a username
* @return 0 if the key starts with the group prefix, otherwise 1
*/
public static int getFirstRoleIndex(String name) {
if (name.trim().startsWith(BackingEngine.GROUP_PREFIX))
return 0;
return 1;
}

public static void addRole(Set<Principal> principals, String role) {
role = role.trim();
if (!role.isEmpty())
principals.add(new RolePrincipal(role.trim()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.Principal;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
Expand Down Expand Up @@ -214,13 +217,13 @@ public boolean login() throws LoginException {
String groupInfo = users.get(infos[i].trim());
if (groupInfo != null) {
String[] roles = groupInfo.split(",");
for (int j = 1; j < roles.length; j++) {
principals.add(new RolePrincipal(roles[j].trim()));
for (int j = 0; j < roles.length; j++) {
addRole(principals, roles[j].trim());
}
}
} else {
// it's an user reference
principals.add(new RolePrincipal(infos[i].trim()));
addRole(principals, infos[i].trim());
}
}

Expand All @@ -233,4 +236,8 @@ public boolean login() throws LoginException {
return true;
}

private void addRole(Set<Principal> principals, String trimmedRole) {
if (!trimmedRole.isEmpty())
principals.add(new RolePrincipal(trimmedRole));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.karaf.jaas.boot.principal.RolePrincipal;
import org.apache.karaf.jaas.boot.principal.UserPrincipal;
import org.apache.karaf.jaas.modules.BackingEngine;
import org.apache.karaf.jaas.modules.JAASUtils;
import org.apache.karaf.jaas.modules.encryption.EncryptionSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -52,14 +53,13 @@ public void addUser(String username, String password) {
if (username.startsWith(GROUP_PREFIX))
throw new IllegalArgumentException("Prefix not permitted: " + GROUP_PREFIX);

addUserInternal(username, password);
addUserInternal(username, encryptionSupport.encrypt(password));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why forcing encryption here ? It's an optional feature.

Copy link
Author

@stataru8 stataru8 Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just moved this call from its original location in addUserInternal:

The call is only needed when adding a user and shouldn't be made when adding a group:

addUserInternal(groupName, ""); // groups don't have password
There is the risk of encrypting "", which with the defaults, results in {CRYPT}ABC...{CRYPT}. After jaas:group-add karaf newGrup,
jaas:user-list will return

User Name | Group   | Role
----------+---------+-------------------------------------------------------------------------------
karaf     | newGrup | {CRYPT}ABC...{CRYPT}

Maybe at this point, we should create another addUserInternal with just the username as an argument: private void addUserInternal(String username), or another function just for groups...

}

private void addUserInternal(String username, String password) {
private void addUserInternal(String username, String encPassword) {
String[] infos = null;
StringBuilder userInfoBuffer = new StringBuilder();

String encPassword = encryptionSupport.encrypt(password);
String userInfos = users.get(username);

//If user already exists, update password
Expand Down Expand Up @@ -139,8 +139,10 @@ private List<RolePrincipal> listRoles(String name) {
List<RolePrincipal> result = new ArrayList<>();
String userInfo = users.get(name);
String[] infos = userInfo.split(",");
for (int i = 1; i < infos.length; i++) {
for (int i = JAASUtils.getFirstRoleIndex(name); i < infos.length; i++) {
String roleName = infos[i];
if (roleName.trim().isEmpty())
continue;
if (roleName.startsWith(GROUP_PREFIX)) {
for (RolePrincipal rp : listRoles(roleName)) {
if (!result.contains(rp)) {
Expand All @@ -161,18 +163,25 @@ private List<RolePrincipal> listRoles(String name) {
public void addRole(String username, String role) {
String userInfos = users.get(username);
if (userInfos != null) {
for (RolePrincipal rp : listRoles(username)) {
if (role.equals(rp.getName())) {
return;
// for groups, empty info should be replaced with role
// for users, empty info means empty password and role should be appended
if (userInfos.trim().isEmpty()
&& username.trim().startsWith(PropertiesBackingEngine.GROUP_PREFIX)) {
users.put(username, role);
} else {
for (RolePrincipal rp : listRoles(username)) {
if (role.equals(rp.getName())) {
return;
}
}
}
for (GroupPrincipal gp : listGroups(username)) {
if (role.equals(GROUP_PREFIX + gp.getName())) {
return;
for (GroupPrincipal gp : listGroups(username)) {
if (role.equals(GROUP_PREFIX + gp.getName())) {
return;
}
}
String newUserInfos = userInfos + "," + role;
users.put(username, newUserInfos);
}
String newUserInfos = userInfos + "," + role;
users.put(username, newUserInfos);
}
try {
users.save();
Expand All @@ -191,12 +200,17 @@ public void deleteRole(String username, String role) {
//If user already exists, remove the role
if (userInfos != null && userInfos.length() > 0) {
infos = userInfos.split(",");
String password = infos[0];
userInfoBuffer.append(password);

for (int i = 1; i < infos.length; i++) {
int firstRoleIndex = JAASUtils.getFirstRoleIndex(username);
if (firstRoleIndex == 1) {// index 0 is password
String password = infos[0];
userInfoBuffer.append(password);
}
for (int i = firstRoleIndex; i < infos.length; i++) {
if (infos[i] != null && !infos[i].equals(role)) {
userInfoBuffer.append(",");
if(userInfoBuffer.length() > 0) {
userInfoBuffer.append(",");
}
userInfoBuffer.append(infos[i]);
}
}
Expand All @@ -222,7 +236,7 @@ private List<GroupPrincipal> listGroups(String userName) {
String userInfo = users.get(userName);
if (userInfo != null) {
String[] infos = userInfo.split(",");
for (int i = 1; i < infos.length; i++) {
for (int i = JAASUtils.getFirstRoleIndex(userName); i < infos.length; i++) {
String name = infos[i];
if (name.startsWith(GROUP_PREFIX)) {
result.add(new GroupPrincipal(name.substring(GROUP_PREFIX.length())));
Expand All @@ -236,7 +250,7 @@ private List<GroupPrincipal> listGroups(String userName) {
public void addGroup(String username, String group) {
String groupName = GROUP_PREFIX + group;
if (users.get(groupName) == null) {
addUserInternal(groupName, "group");
addUserInternal(groupName, ""); // groups don't have password
}
addRole(username, groupName);
}
Expand Down Expand Up @@ -282,7 +296,7 @@ public Map<GroupPrincipal, String> listGroups() {
public void createGroup(String group) {
String groupName = GROUP_PREFIX + group;
if (users.get(groupName) == null) {
addUserInternal(groupName, "group");
addUserInternal(groupName, ""); // groups don't have password
} else {
throw new IllegalArgumentException("Group: " + group + " already exist");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
Expand All @@ -31,7 +32,6 @@

import org.apache.felix.utils.properties.Properties;
import org.apache.karaf.jaas.boot.principal.GroupPrincipal;
import org.apache.karaf.jaas.boot.principal.RolePrincipal;
import org.apache.karaf.jaas.boot.principal.UserPrincipal;
import org.apache.karaf.jaas.modules.AbstractKarafLoginModule;
import org.apache.karaf.jaas.modules.JAASUtils;
Expand Down Expand Up @@ -141,13 +141,13 @@ public boolean login() throws LoginException {
String groupInfo = users.get(infos[i].trim());
if (groupInfo != null) {
String[] roles = groupInfo.split(",");
for (int j = 1; j < roles.length; j++) {
principals.add(new RolePrincipal(roles[j].trim()));
for (int j = 0; j < roles.length; j++) {
JAASUtils.addRole(principals, roles[j]);
}
}
} else {
// it's an user reference
principals.add(new RolePrincipal(infos[i].trim()));
JAASUtils.addRole(principals, infos[i]);
}
}

Expand All @@ -159,5 +159,4 @@ public boolean login() throws LoginException {
succeeded = true;
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.karaf.jaas.boot.principal.RolePrincipal;
import org.apache.karaf.jaas.boot.principal.UserPrincipal;
import org.apache.karaf.jaas.modules.BackingEngine;
import org.apache.karaf.jaas.modules.JAASUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -132,8 +133,10 @@ private List<RolePrincipal> listRoles(String name) {
List<RolePrincipal> result = new ArrayList<>();
String userInfo = users.get(name);
String[] infos = userInfo.split(",");
for (int i = 1; i < infos.length; i++) {
for (int i = JAASUtils.getFirstRoleIndex(name); i < infos.length; i++) {
String roleName = infos[i];
if (roleName.trim().isEmpty())
continue;
if (roleName.startsWith(GROUP_PREFIX)) {
for (RolePrincipal rp : listRoles(roleName)) {
if (!result.contains(rp)) {
Expand All @@ -154,13 +157,25 @@ private List<RolePrincipal> listRoles(String name) {
public void addRole(String username, String role) {
String userInfos = users.get(username);
if (userInfos != null) {
for (RolePrincipal rp : listRoles(username)) {
if (role.equals(rp.getName())) {
return;
// for groups, empty info should be replaced with role
// for users, empty info means empty password and role should be appended
if (userInfos.trim().isEmpty()
&& username.trim().startsWith(GROUP_PREFIX)) {
users.put(username, role);
} else {
for (RolePrincipal rp : listRoles(username)) {
if (role.equals(rp.getName())) {
return;
}
}
for (GroupPrincipal gp : listGroups(username)) {
if (role.equals(GROUP_PREFIX + gp.getName())) {
return;
}
}
String newUserInfos = userInfos + "," + role;
users.put(username, newUserInfos);
}
String newUserInfos = userInfos + "," + role;
users.put(username, newUserInfos);
}
try {
users.save();
Expand All @@ -179,12 +194,17 @@ public void deleteRole(String username, String role) {
//If user already exists, remove the role
if (userInfos != null && userInfos.length() > 0) {
infos = userInfos.split(",");
String password = infos[0];
userInfoBuffer.append(password);

for (int i = 1; i < infos.length; i++) {
int firstRoleIndex = JAASUtils.getFirstRoleIndex(username);
if (firstRoleIndex == 1) {// index 0 is password
String password = infos[0];
userInfoBuffer.append(password);
}
for (int i = firstRoleIndex; i < infos.length; i++) {
if (infos[i] != null && !infos[i].equals(role)) {
userInfoBuffer.append(",");
if(userInfoBuffer.length() > 0) {
userInfoBuffer.append(",");
}
userInfoBuffer.append(infos[i]);
}
}
Expand All @@ -210,7 +230,7 @@ private List<GroupPrincipal> listGroups(String userName) {
String userInfo = users.get(userName);
if (userInfo != null) {
String[] infos = userInfo.split(",");
for (int i = 1; i < infos.length; i++) {
for (int i = JAASUtils.getFirstRoleIndex(userName); i < infos.length; i++) {
String name = infos[i];
if (name.startsWith(GROUP_PREFIX)) {
result.add(new GroupPrincipal(name.substring(GROUP_PREFIX.length())));
Expand All @@ -224,7 +244,7 @@ private List<GroupPrincipal> listGroups(String userName) {
public void addGroup(String username, String group) {
String groupName = GROUP_PREFIX + group;
if (users.get(groupName) == null) {
addUserInternal(groupName, "group");
addUserInternal(groupName, ""); // groups don't have public key
}
addRole(username, groupName);
}
Expand Down Expand Up @@ -270,7 +290,7 @@ public Map<GroupPrincipal, String> listGroups() {
public void createGroup(String group) {
String groupName = GROUP_PREFIX + group;
if (users.get(groupName) == null) {
addUserInternal(groupName, "group");
addUserInternal(groupName, ""); // groups don't have public key
} else {
throw new IllegalArgumentException("Group: " + group + " already exist");
}
Expand Down
Loading