/* * Copyright (C) 2014 Intel Corporation * All rights reserved. */ package com.intel.mtwilson.setup.console.cmd; import com.intel.dcsg.cpg.console.Command; import com.intel.dcsg.cpg.console.input.Input; import com.intel.dcsg.cpg.crypto.RandomUtil; import com.intel.dcsg.cpg.i18n.LocaleUtil; import com.intel.dcsg.cpg.io.UUID; import com.intel.mtwilson.shiro.jdbi.LoginDAO; import org.apache.commons.configuration.Configuration; import com.intel.mtwilson.crypto.password.PasswordUtil; import com.intel.mtwilson.user.management.rest.v2.model.UserLoginPassword; // file.model.UserPassword; import com.intel.mtwilson.user.management.rest.v2.model.RolePermission; // file.model.UserPermission; import com.intel.mtwilson.shiro.jdbi.MyJdbi; import com.intel.mtwilson.user.management.rest.v2.model.Role; import com.intel.mtwilson.user.management.rest.v2.model.Status; import com.intel.mtwilson.user.management.rest.v2.model.User; import com.intel.mtwilson.user.management.rest.v2.model.UserLoginPasswordRole; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Usage examples: login-password username password --permissions domain:action * login-password username password --permissions domain1:action1 * domain2:action2 domain3:action3 ... login-password username --nopass * --permissions domain:action login-password username --nopass --permissions * domain1:action1 domain2:action2 domain3:action3 ... * * @author jbuhacoff */ public class LoginPassword implements Command { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoginPassword.class); // private TrustagentConfiguration configuration; private Configuration options; @Override public void setOptions(Configuration options) { this.options = options; } protected boolean isEmptyPassword() { return options.getBoolean("nopass", false); } // never returns null but password may be empty (and that's allowed) private String getPassword(String[] args) throws IOException { String password; if (isEmptyPassword()) { password = ""; } else if (args.length > 1) { password = args[1]; // always after username if present if (password == null || password.isEmpty()) { throw new IllegalArgumentException("Password is empty"); } if (password.startsWith("env:") && password.length() > 4) { String variableName = password.substring(4); password = System.getenv(variableName); if (password == null || password.isEmpty()) { throw new IllegalArgumentException(String.format("Environment variable %s does not contain a password", variableName)); } } } else { password = Input.getConfirmedPasswordWithPrompt(String.format("Choose a password for %s", args[0])); // throws IOException, or always returns value or expression if (password == null || password.isEmpty()) { throw new IllegalArgumentException("Input password is empty"); } } return password; } // get the 3rd arg if it's usrename passsword permissions, or the 2nd arg if it's username --nopass permissions private List<RolePermission> getPermissions(String[] args) { int i = 2; // login-password 0<username> 1<password> 2<permissions...> if (isEmptyPassword()) { i = 1; // login-password 0<username> 1<permissions...> } ArrayList<RolePermission> list = new ArrayList<>(); for (; i < args.length; i++) { RolePermission rp = new RolePermission(); String permissions = args[i]; String[] parts = permissions.split(":"); if (parts.length == 3) { rp.setPermitDomain(parts[0]); rp.setPermitAction(parts[1]); rp.setPermitSelection(parts[2]); } else if (parts.length == 2) { rp.setPermitDomain(parts[0]); rp.setPermitAction(parts[1]); rp.setPermitSelection("*"); } else if (parts.length == 1) { rp.setPermitDomain(parts[0]); rp.setPermitAction("*"); rp.setPermitSelection("*"); } else { throw new IllegalArgumentException("Invalid permission format"); // must be in the form domain:action:instance or domain:action or domain } list.add(rp); } return list; } @Override public void execute(String[] args) throws Exception { // store or replace the user record log.debug("Loading users and permissions"); // usage: username (prompt for password, no permissions) // usage: username password (no permissions) // usage: username password permissions // usage: username --nopass (no permissions) // usage: username --nopass permissions // usage: username --remove String username = args[0]; if (options.getBoolean("remove", false)) { removeUser(username); removePermissions(username); log.debug("Removed username {}", username); return; } String password = getPassword(args); // never returns null but password may be empty try (LoginDAO dao = MyJdbi.authz()) { // create the new user record // removeUser(username); User user = dao.findUserByName(username); if (user == null) { user = new User(); user.setId(new UUID()); //user.setComment("automatically created by setup"); user.setUsername(username); dao.insertUser(user.getId(), user.getUsername(), null, ""); log.info("Created user {}", username); } else { String localeTag = null; if (user.getLocale() != null) localeTag = LocaleUtil.toLanguageTag(user.getLocale()); dao.updateUser(user.getId(), localeTag, user.getComment()); log.debug("Updated User: {}", username); } UserLoginPassword userLoginPassword = dao.findUserLoginPasswordByUsername(username); if (userLoginPassword == null) { userLoginPassword = new UserLoginPassword(); userLoginPassword.setId(new UUID()); userLoginPassword.setUserId(user.getId()); userLoginPassword.setAlgorithm("SHA256"); userLoginPassword.setIterations(1); userLoginPassword.setSalt(RandomUtil.randomByteArray(8)); userLoginPassword.setPasswordHash(PasswordUtil.hash(password.getBytes(), userLoginPassword)); userLoginPassword.setEnabled(true); userLoginPassword.setStatus(Status.APPROVED); userLoginPassword.setComment("Automatically created during setup."); dao.insertUserLoginPassword(userLoginPassword.getId(), userLoginPassword.getUserId(), userLoginPassword.getPasswordHash(), userLoginPassword.getSalt(), userLoginPassword.getIterations(), userLoginPassword.getAlgorithm(), userLoginPassword.getExpires(), userLoginPassword.isEnabled(), userLoginPassword.getStatus(), userLoginPassword.getComment()); log.debug("Stored UserLoginPassword with ID: {}", userLoginPassword.getId()); } else { userLoginPassword.setUserId(user.getId()); userLoginPassword.setAlgorithm("SHA256"); userLoginPassword.setIterations(1); userLoginPassword.setSalt(RandomUtil.randomByteArray(8)); userLoginPassword.setPasswordHash(PasswordUtil.hash(password.getBytes(), userLoginPassword)); userLoginPassword.setEnabled(true); userLoginPassword.setStatus(Status.APPROVED); userLoginPassword.setComment("Automatically created during setup."); dao.updateUserLoginPasswordWithUserId(userLoginPassword.getId(), userLoginPassword.getUserId(), userLoginPassword.getPasswordHash(), userLoginPassword.getSalt(), userLoginPassword.getIterations(), userLoginPassword.getAlgorithm(), userLoginPassword.getExpires(), userLoginPassword.isEnabled(), userLoginPassword.getStatus(), userLoginPassword.getComment()); log.debug("Updated UserLoginPassword with ID: {}", userLoginPassword.getId()); } log.debug("finding role by username"); Role userRole = dao.findRoleByName(username); if (userRole == null) { log.debug("roles not found for username"); userRole = new Role(); userRole.setId(new UUID()); userRole.setRoleName(username); userRole.setDescription("user created role"); dao.insertRole(userRole.getId(), userRole.getRoleName(), userRole.getDescription()); log.debug("Stored user role [{}] with ID: {}", username, userRole.getId()); } log.debug("finding user login password roles by user login password id"); List<UserLoginPasswordRole> userLoginPasswordRoles = dao.findUserLoginPasswordRolesByUserLoginPasswordId(userLoginPassword.getId()); if (userLoginPasswordRoles == null || userLoginPasswordRoles.isEmpty()) { dao.insertUserLoginPasswordRole(userLoginPassword.getId(), userRole.getId()); } else { // try to find the user's custom role in the list of existing roles List<String> userLoginPasswordRoleIds = getRoleUuidHexList(userLoginPasswordRoles); if (userLoginPasswordRoleIds.contains(userRole.getId().toHexString())) { log.debug("user login password already linked to custom role"); } else { log.debug("Inserting user login password role id {} role id {}", userLoginPassword.getId(), userRole.getId()); dao.insertUserLoginPasswordRole(userLoginPassword.getId(), userRole.getId()); } } log.debug("removing permissions"); removePermissions(username); log.debug("getting permissions"); List<RolePermission> newPermissions = getPermissions(args); for (RolePermission newPermission : newPermissions) { newPermission.setRoleId(userRole.getId()); dao.insertRolePermission(newPermission.getRoleId(), newPermission.getPermitDomain(), newPermission.getPermitAction(), newPermission.getPermitSelection()); log.debug("Stored permissions {}", newPermissions); } } } private void removeUser(String username) throws IOException, SQLException { try (LoginDAO dao = MyJdbi.authz()) { UserLoginPassword existingUserLoginPassword = dao.findUserLoginPasswordByUsername(username); if (existingUserLoginPassword != null) { dao.deleteUser(existingUserLoginPassword.getUserId()); log.info("Deleted user {}", username); } } } private void removePermissions(String username) throws IOException, SQLException { try (LoginDAO dao = MyJdbi.authz()) { log.debug("finding existing user login password by username"); UserLoginPassword existingUserLoginPassword = dao.findUserLoginPasswordByUsername(username); if (existingUserLoginPassword == null) { log.debug("No user found for username: {}", username); return; } log.debug("finding existing roles by user login password id"); Set<UUID> roleUuidList = getRoleUuids(dao.findRolesByUserLoginPasswordId(existingUserLoginPassword.getId())); if (roleUuidList.isEmpty()) { log.debug("No role list found for user: {}", existingUserLoginPassword.getId()); return; } log.debug("finding role permisiosn by password role ids {}", roleUuidList); List<RolePermission> existingPermissions = dao.findRolePermissionsByPasswordRoleIds(toStrings(roleUuidList)); log.debug("got permissions {}", existingPermissions); for (RolePermission existingPermission : existingPermissions) { log.debug("deleting role permission"); dao.deleteRolePermission(existingPermission.getRoleId(), existingPermission.getPermitDomain(), existingPermission.getPermitAction(), existingPermission.getPermitSelection()); log.debug("Deleted role permission with role ID: {}, domain: {}, action: {}, selection: {}", existingPermission.getRoleId(), existingPermission.getPermitDomain(), existingPermission.getPermitAction(), existingPermission.getPermitSelection()); } } } Set<UUID> getRoleUuids(List<Role> roles) { HashSet<UUID> uuids = new HashSet<>(); for (Role role : roles) { uuids.add(role.getId()); } return uuids; } List<String> getRoleUuidHexList(List<UserLoginPasswordRole> userLoginPasswordRoles) { ArrayList<String> ids = new ArrayList<>(); for (UserLoginPasswordRole userLoginPasswordRole : userLoginPasswordRoles) { ids.add(userLoginPasswordRole.getRoleId().toHexString()); } return ids; } // see also CreateAdminUser command private Set<String> toStrings(Set<UUID> uuids) { HashSet<String> set = new HashSet<>(); for (UUID uuid : uuids) { set.add(uuid.toString()); } return set; } }