mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Summary: Make the authenticator responsible for encoding the password and add a SHA256 salted authenticator
The authenticators now have an encode function that cloudstack will use to encode the user supplied password before storing it in the database. This makes it easier to add other authenticators with other hashing algorithms. The requires a two step approach to creating the admin account at first start as the authenticators are only present in the management-server component locator. The SHA256 salted authenticator make use of this new system and adds a hashing algorithm based on SHA256 with a salt. This type of hash is far less susceptible to rainbow table attacks. To make use of these new features the users password will be sent over the wire just as he typed it and it will be transformed into a hash on the server and compared with the stored password. This means that the hash will not go over the wire anymore. The default authenticator in components.xml is still set to md5 for backwards compatibility. For new installations the sha256 could be enabled.
This commit is contained in:
parent
07d555db37
commit
bd58ceccd8
@ -40,6 +40,11 @@
|
||||
<artifactId>cloud-plugin-user-authenticator-plaintext</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-user-authenticator-sha256salted</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-network-nvp</artifactId>
|
||||
|
||||
@ -109,6 +109,7 @@ under the License.
|
||||
<adapter name="Basic" class="com.cloud.network.ExteralIpAddressAllocator"/>
|
||||
</adapters>
|
||||
<adapters key="com.cloud.server.auth.UserAuthenticator">
|
||||
<!-- <adapter name="SHA256SALT" class="com.cloud.server.auth.SHA256SaltedUserAuthenticator"/> -->
|
||||
<adapter name="MD5" class="com.cloud.server.auth.MD5UserAuthenticator"/>
|
||||
<adapter name="LDAP" class="com.cloud.server.auth.LDAPUserAuthenticator"/>
|
||||
</adapters>
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
<module>user-authenticators/ldap</module>
|
||||
<module>user-authenticators/md5</module>
|
||||
<module>user-authenticators/plain-text</module>
|
||||
<module>user-authenticators/sha256salted</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
//
|
||||
package com.cloud.server.auth;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
@ -31,6 +33,7 @@ import javax.naming.directory.SearchControls;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import com.cloud.api.ApiConstants.LDAPParams;
|
||||
import com.cloud.configuration.Config;
|
||||
@ -40,6 +43,7 @@ import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.dao.UserAccountDao;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
|
||||
@Local(value={UserAuthenticator.class})
|
||||
@ -159,4 +163,17 @@ public class LDAPUserAuthenticator extends DefaultUserAuthenticator {
|
||||
_userAccountDao = locator.getDao(UserAccountDao.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(String password) {
|
||||
// Password is not used, so set to a random string
|
||||
try {
|
||||
SecureRandom randomGen = SecureRandom.getInstance("SHA1PRNG");
|
||||
byte bytes[] = new byte[20];
|
||||
randomGen.nextBytes(bytes);
|
||||
return Base64.encode(bytes).toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CloudRuntimeException("Failed to generate random password",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,9 @@
|
||||
|
||||
package com.cloud.server.auth;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
@ -26,6 +29,7 @@ import com.cloud.server.ManagementServer;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.dao.UserAccountDao;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
/**
|
||||
* Simple UserAuthenticator that performs a MD5 hash of the password before
|
||||
@ -49,31 +53,7 @@ public class MD5UserAuthenticator extends DefaultUserAuthenticator {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
MessageDigest md5;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CloudRuntimeException("Error", e);
|
||||
}
|
||||
md5.reset();
|
||||
BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes()));
|
||||
|
||||
// make sure our MD5 hash value is 32 digits long...
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String pwStr = pwInt.toString(16);
|
||||
int padding = 32 - pwStr.length();
|
||||
for (int i = 0; i < padding; i++) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(pwStr);
|
||||
**/
|
||||
|
||||
// Will: The MD5Authenticator is now a straight pass-through comparison of the
|
||||
// the passwords because we will not assume that the password passed in has
|
||||
// already been MD5 hashed. I am keeping the above code in case this requirement changes
|
||||
// or people need examples of how to MD5 hash passwords in java.
|
||||
if (!user.getPassword().equals(password)) {
|
||||
if (!user.getPassword().equals(encode(password))) {
|
||||
s_logger.debug("Password does not match");
|
||||
return false;
|
||||
}
|
||||
@ -87,4 +67,25 @@ public class MD5UserAuthenticator extends DefaultUserAuthenticator {
|
||||
_userAccountDao = locator.getDao(UserAccountDao.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(String password) {
|
||||
MessageDigest md5 = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CloudRuntimeException("Unable to hash password", e);
|
||||
}
|
||||
|
||||
md5.reset();
|
||||
BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes()));
|
||||
String pwStr = pwInt.toString(16);
|
||||
int padding = 32 - pwStr.length();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < padding; i++) {
|
||||
sb.append('0'); // make sure the MD5 password is 32 digits long
|
||||
}
|
||||
sb.append(pwStr);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,4 +87,10 @@ public class PlainTextUserAuthenticator extends DefaultUserAuthenticator {
|
||||
_userAccountDao = locator.getDao(UserAccountDao.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(String password) {
|
||||
// Plaintext so no encoding at all
|
||||
return password;
|
||||
}
|
||||
}
|
||||
|
||||
29
plugins/user-authenticators/sha256salted/pom.xml
Normal file
29
plugins/user-authenticators/sha256salted/pom.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-user-authenticator-sha256salted</artifactId>
|
||||
<name>Apache CloudStack Plugin - User Authenticator SHA256 Salted</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
</project>
|
||||
@ -0,0 +1,122 @@
|
||||
// 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 com.cloud.server.auth;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import com.cloud.server.ManagementServer;
|
||||
import com.cloud.servlet.CloudStartupServlet;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.dao.UserAccountDao;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Local(value={UserAuthenticator.class})
|
||||
public class SHA256SaltedUserAuthenticator extends DefaultUserAuthenticator {
|
||||
public static final Logger s_logger = Logger.getLogger(SHA256SaltedUserAuthenticator.class);
|
||||
|
||||
@Inject
|
||||
private UserAccountDao _userAccountDao;
|
||||
private static int s_saltlen = 20;
|
||||
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
super.configure(name, params);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.server.auth.UserAuthenticator#authenticate(java.lang.String, java.lang.String, java.lang.Long, java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public boolean authenticate(String username, String password,
|
||||
Long domainId, Map<String, Object[]> requestParameters) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Retrieving user: " + username);
|
||||
}
|
||||
UserAccount user = _userAccountDao.getUserAccount(username, domainId);
|
||||
if (user == null) {
|
||||
s_logger.debug("Unable to find user with " + username + " in domain " + domainId);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
String storedPassword[] = user.getPassword().split(":");
|
||||
if (storedPassword.length != 2) {
|
||||
s_logger.warn("The stored password for " + username + " isn't in the right format for this authenticator");
|
||||
return false;
|
||||
}
|
||||
byte salt[] = Base64.decode(storedPassword[0]);
|
||||
String hashedPassword = encode(password, salt);
|
||||
return storedPassword[1].equals(hashedPassword);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CloudRuntimeException("Unable to hash password", e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new CloudRuntimeException("Unable to hash password", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.server.auth.UserAuthenticator#encode(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public String encode(String password) {
|
||||
// 1. Generate the salt
|
||||
SecureRandom randomGen;
|
||||
try {
|
||||
randomGen = SecureRandom.getInstance("SHA1PRNG");
|
||||
|
||||
byte salt[] = new byte[s_saltlen];
|
||||
randomGen.nextBytes(salt);
|
||||
|
||||
String saltString = new String(Base64.encode(salt));
|
||||
String hashString = encode(password, salt);
|
||||
|
||||
// 3. concatenate the two and return
|
||||
return saltString + ":" + hashString;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new CloudRuntimeException("Unable to hash password", e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new CloudRuntimeException("Unable to hash password", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String encode(String password, byte[] salt) throws UnsupportedEncodingException, NoSuchAlgorithmException {
|
||||
byte[] passwordBytes = password.getBytes("UTF-8");
|
||||
byte[] hashSource = new byte[passwordBytes.length + s_saltlen];
|
||||
System.arraycopy(passwordBytes, 0, hashSource, 0, passwordBytes.length);
|
||||
System.arraycopy(salt, 0, hashSource, passwordBytes.length, s_saltlen);
|
||||
|
||||
// 2. Hash the password with the salt
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
md.update(hashSource);
|
||||
byte[] digest = md.digest();
|
||||
|
||||
return new String(Base64.encode(digest));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package src.com.cloud.server.auth.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.cloud.server.auth.SHA256SaltedUserAuthenticator;
|
||||
|
||||
public class AuthenticatorTest {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncode() throws UnsupportedEncodingException, NoSuchAlgorithmException {
|
||||
SHA256SaltedUserAuthenticator authenticator =
|
||||
new SHA256SaltedUserAuthenticator();
|
||||
|
||||
try {
|
||||
authenticator.configure("SHA256", Collections.<String,Object>emptyMap());
|
||||
} catch (ConfigurationException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
|
||||
String encodedPassword = authenticator.encode("password");
|
||||
|
||||
String storedPassword[] = encodedPassword.split(":");
|
||||
assertEquals ("hash must consist of two components", storedPassword.length, 2);
|
||||
|
||||
byte salt[] = Base64.decode(storedPassword[0]);
|
||||
String hashedPassword = authenticator.encode("password", salt);
|
||||
|
||||
assertEquals("compare hashes", storedPassword[1], hashedPassword);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -32,6 +32,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -85,6 +86,7 @@ import com.cloud.offerings.NetworkOfferingServiceMapVO;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
|
||||
import com.cloud.server.auth.UserAuthenticator;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
@ -96,6 +98,7 @@ import com.cloud.user.User;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.PasswordGenerator;
|
||||
import com.cloud.utils.PropertiesUtil;
|
||||
import com.cloud.utils.component.Adapters;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.crypt.DBEncryptionUtil;
|
||||
import com.cloud.utils.db.DB;
|
||||
@ -342,30 +345,13 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
||||
} catch (SQLException ex) {
|
||||
}
|
||||
|
||||
// insert admin user
|
||||
// insert admin user, but leave the account disabled until we set a
|
||||
// password with the user authenticator
|
||||
long id = 2;
|
||||
String username = "admin";
|
||||
String firstname = "admin";
|
||||
String lastname = "cloud";
|
||||
String password = "password";
|
||||
|
||||
MessageDigest md5 = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
md5.reset();
|
||||
BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes()));
|
||||
String pwStr = pwInt.toString(16);
|
||||
int padding = 32 - pwStr.length();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < padding; i++) {
|
||||
sb.append('0'); // make sure the MD5 password is 32 digits long
|
||||
}
|
||||
sb.append(pwStr);
|
||||
|
||||
|
||||
// create an account for the admin user first
|
||||
insertSql = "INSERT INTO `cloud`.`account` (id, account_name, type, domain_id) VALUES (" + id + ", '" + username + "', '1', '1')";
|
||||
txn = Transaction.currentTxn();
|
||||
@ -376,8 +362,8 @@ public class ConfigurationServerImpl implements ConfigurationServer {
|
||||
}
|
||||
|
||||
// now insert the user
|
||||
insertSql = "INSERT INTO `cloud`.`user` (id, username, password, account_id, firstname, lastname, created) " +
|
||||
"VALUES (" + id + ",'" + username + "','" + sb.toString() + "', 2, '" + firstname + "','" + lastname + "',now())";
|
||||
insertSql = "INSERT INTO `cloud`.`user` (id, username, account_id, firstname, lastname, created, state) " +
|
||||
"VALUES (" + id + ",'" + username + "', 2, '" + firstname + "','" + lastname + "',now(), 'disabled')";
|
||||
|
||||
txn = Transaction.currentTxn();
|
||||
try {
|
||||
|
||||
@ -95,4 +95,6 @@ public interface ManagementServer extends ManagementService {
|
||||
Pair<List<StoragePoolVO>, Integer> searchForStoragePools(Criteria c);
|
||||
|
||||
String getHashKey();
|
||||
|
||||
public void enableAdminUser(String password);
|
||||
}
|
||||
|
||||
@ -177,6 +177,7 @@ import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
||||
import com.cloud.projects.ProjectManager;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.server.ResourceTag.TaggedResourceType;
|
||||
import com.cloud.server.auth.UserAuthenticator;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
@ -215,7 +216,9 @@ import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.SSHKeyPair;
|
||||
import com.cloud.user.SSHKeyPairVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserAccount;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.user.dao.SSHKeyPairDao;
|
||||
import com.cloud.user.dao.UserDao;
|
||||
@ -338,6 +341,8 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
private final StatsCollector _statsCollector;
|
||||
|
||||
private final Map<String, Boolean> _availableIdsMap;
|
||||
|
||||
private Adapters<UserAuthenticator> _userAuthenticators;
|
||||
|
||||
private String _hashKey = null;
|
||||
|
||||
@ -417,6 +422,11 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
for (String id : availableIds) {
|
||||
_availableIdsMap.put(id, true);
|
||||
}
|
||||
|
||||
_userAuthenticators = locator.getAdapters(UserAuthenticator.class);
|
||||
if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
|
||||
s_logger.error("Unable to find an user authenticator.");
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, String> getConfigs() {
|
||||
@ -3587,5 +3597,28 @@ public class ManagementServerImpl implements ManagementServer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void enableAdminUser(String password) {
|
||||
String encodedPassword = null;
|
||||
|
||||
UserVO adminUser = _userDao.getUser(2);
|
||||
if (adminUser.getState() == Account.State.disabled) {
|
||||
// This means its a new account, set the password using the authenticator
|
||||
|
||||
for (Enumeration<UserAuthenticator> en = _userAuthenticators.enumeration(); en.hasMoreElements();) {
|
||||
UserAuthenticator authenticator = en.nextElement();
|
||||
encodedPassword = authenticator.encode(password);
|
||||
if (encodedPassword != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
adminUser.setPassword(encodedPassword);
|
||||
adminUser.setState(Account.State.enabled);
|
||||
_userDao.persist(adminUser);
|
||||
s_logger.info("Admin user enabled");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,4 +34,10 @@ public interface UserAuthenticator extends Adapter {
|
||||
* @return true if the user has been successfully authenticated, false otherwise
|
||||
*/
|
||||
public boolean authenticate(String username, String password, Long domainId, Map<String, Object[]> requestParameters);
|
||||
|
||||
/**
|
||||
* @param password
|
||||
* @return the encoded password
|
||||
*/
|
||||
public String encode(String password);
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ public class CloudStartupServlet extends HttpServlet implements ServletContextLi
|
||||
c.persistDefaultValues();
|
||||
s_locator = ComponentLocator.getLocator(ManagementServer.Name);
|
||||
ManagementServer ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name);
|
||||
ms.enableAdminUser("password");
|
||||
ApiServer.initApiServer(ms.getApiConfig());
|
||||
} catch (InvalidParameterValueException ipve) {
|
||||
s_logger.error("Exception starting management server ", ipve);
|
||||
|
||||
@ -921,7 +921,18 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
user.setPassword(password);
|
||||
String encodedPassword = null;
|
||||
for (Enumeration<UserAuthenticator> en = _userAuthenticators.enumeration(); en.hasMoreElements();) {
|
||||
UserAuthenticator authenticator = en.nextElement();
|
||||
encodedPassword = authenticator.encode(password);
|
||||
if (encodedPassword != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encodedPassword == null) {
|
||||
throw new CloudRuntimeException("Failed to encode password");
|
||||
}
|
||||
user.setPassword(encodedPassword);
|
||||
}
|
||||
if (email != null) {
|
||||
user.setEmail(email);
|
||||
@ -1670,7 +1681,20 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone);
|
||||
}
|
||||
UserVO user = _userDao.persist(new UserVO(accountId, userName, password, firstName, lastName, email, timezone));
|
||||
|
||||
String encodedPassword = null;
|
||||
for (Enumeration<UserAuthenticator> en = _userAuthenticators.enumeration(); en.hasMoreElements();) {
|
||||
UserAuthenticator authenticator = en.nextElement();
|
||||
encodedPassword = authenticator.encode(password);
|
||||
if (encodedPassword != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encodedPassword == null) {
|
||||
throw new CloudRuntimeException("Failed to encode password");
|
||||
}
|
||||
|
||||
UserVO user = _userDao.persist(new UserVO(accountId, userName, encodedPassword, firstName, lastName, email, timezone));
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@ -37,8 +37,8 @@ var ERROR_INTERNET_CANNOT_CONNECT = 12029;
|
||||
var ERROR_VMOPS_ACCOUNT_ERROR = 531;
|
||||
|
||||
// Default password is MD5 hashed. Set the following variable to false to disable this.
|
||||
var md5Hashed = true;
|
||||
var md5HashedLogin = true;
|
||||
var md5Hashed = false;
|
||||
var md5HashedLogin = false;
|
||||
|
||||
//page size for API call (e.g."listXXXXXXX&pagesize=N" )
|
||||
var pageSize = 20;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user