CLOUDSTACK-9632: Upgrade bouncy castle to version 1.55

- Upgrades Maven dependency version to v1.55
- Fixes bountycastle usages and issues
- Adds timeout to jetty/annotation scanning
- Fixes servlet issue, uses servlet 3.1.0
- Downgrade javassist used by reflections to fix annotation process errors
- Make console-proxy-rdp bc dependency same as rest of the codebase
- Picks up PR #1510 by Daan

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2016-11-30 15:01:28 +05:30
parent 8d506a624b
commit abfcd5b95f
18 changed files with 1427 additions and 1537 deletions

View File

@ -37,7 +37,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>${cs.servlet.version}</version> <version>${cs.servlet.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -2399,7 +2399,6 @@ public class Upgrade410to420 implements DbUpgrade {
//implies iso_id1 is not present, so do nothing. //implies iso_id1 is not present, so do nothing.
} }
} catch (SQLException e) { } catch (SQLException e) {
s_logger.error("migrateDatafromIsoIdInVolumesTable:Exception:"+e.getMessage(),e);
//implies iso_id1 is not present, so do nothing. //implies iso_id1 is not present, so do nothing.
} }
} }

View File

@ -18,14 +18,7 @@
*/ */
package org.apache.cloudstack.framework.server; package org.apache.cloudstack.framework.server;
import java.util.HashMap; import com.cloud.utils.concurrency.NamedThreadFactory;
import java.util.Map;
import java.security.SecureRandom;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;
import org.apache.cloudstack.framework.serializer.MessageSerializer; import org.apache.cloudstack.framework.serializer.MessageSerializer;
import org.apache.cloudstack.framework.transport.TransportAddress; import org.apache.cloudstack.framework.transport.TransportAddress;
import org.apache.cloudstack.framework.transport.TransportDataPdu; import org.apache.cloudstack.framework.transport.TransportDataPdu;
@ -34,8 +27,15 @@ import org.apache.cloudstack.framework.transport.TransportEndpointSite;
import org.apache.cloudstack.framework.transport.TransportPdu; import org.apache.cloudstack.framework.transport.TransportPdu;
import org.apache.cloudstack.framework.transport.TransportProvider; import org.apache.cloudstack.framework.transport.TransportProvider;
import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.cloud.utils.concurrency.NamedThreadFactory; import java.security.SecureRandom;
import java.security.Security;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerTransportProvider implements TransportProvider { public class ServerTransportProvider implements TransportProvider {
private static final Logger s_logger = Logger.getLogger(ServerTransportProvider.class); private static final Logger s_logger = Logger.getLogger(ServerTransportProvider.class);
@ -52,9 +52,16 @@ public class ServerTransportProvider implements TransportProvider {
private MessageSerializer _messageSerializer; private MessageSerializer _messageSerializer;
static {
BouncyCastleProvider provider = new BouncyCastleProvider();
if (Security.getProvider(provider.getName()) == null) {
Security.addProvider(provider);
}
}
public ServerTransportProvider() { public ServerTransportProvider() {
randomGenerator=new SecureRandom(); randomGenerator = new SecureRandom();
_nextEndpointId=randomGenerator.nextInt(); _nextEndpointId = randomGenerator.nextInt();
} }
public String getNodeId() { public String getNodeId() {

View File

@ -29,7 +29,7 @@ public class TransportAddress {
private int _connectionId = LOCAL_SERVICE_CONNECTION; private int _connectionId = LOCAL_SERVICE_CONNECTION;
private String _endpointId; private String _endpointId;
private int _magic; private int _magic;
private final SecureRandom randomGenerator=new SecureRandom(); private final SecureRandom randomGenerator = new SecureRandom();
public TransportAddress(String nodeId, int connectionId, String endpointId) { public TransportAddress(String nodeId, int connectionId, String endpointId) {
assert (nodeId != null); assert (nodeId != null);

View File

@ -30,6 +30,7 @@ import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
import com.google.common.base.Strings;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -48,7 +49,7 @@ public class KeystoreManagerImpl extends ManagerBase implements KeystoreManager
@Override @Override
public boolean validateCertificate(String certificate, String key, String domainSuffix) { public boolean validateCertificate(String certificate, String key, String domainSuffix) {
if (certificate == null || certificate.isEmpty() || key == null || key.isEmpty() || domainSuffix == null || domainSuffix.isEmpty()) { if (Strings.isNullOrEmpty(certificate) || Strings.isNullOrEmpty(key) || Strings.isNullOrEmpty(domainSuffix)) {
s_logger.error("Invalid parameter found in (certificate, key, domainSuffix) tuple for domain: " + domainSuffix); s_logger.error("Invalid parameter found in (certificate, key, domainSuffix) tuple for domain: " + domainSuffix);
return false; return false;
} }

View File

@ -44,7 +44,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>

12
pom.xml
View File

@ -71,7 +71,7 @@
<cs.junit.version>4.12</cs.junit.version> <cs.junit.version>4.12</cs.junit.version>
<cs.hamcrest.version>1.3</cs.hamcrest.version> <cs.hamcrest.version>1.3</cs.hamcrest.version>
<cs.junit.dataprovider.version>1.10.0</cs.junit.dataprovider.version> <cs.junit.dataprovider.version>1.10.0</cs.junit.dataprovider.version>
<cs.bcprov.version>1.46</cs.bcprov.version> <cs.bcprov.version>1.55</cs.bcprov.version>
<cs.jsch.version>0.1.53</cs.jsch.version> <cs.jsch.version>0.1.53</cs.jsch.version>
<cs.jpa.version>2.1.1</cs.jpa.version> <cs.jpa.version>2.1.1</cs.jpa.version>
<cs.jasypt.version>1.9.2</cs.jasypt.version> <cs.jasypt.version>1.9.2</cs.jasypt.version>
@ -93,7 +93,7 @@
<cs.rampart.version>1.5.1</cs.rampart.version> <cs.rampart.version>1.5.1</cs.rampart.version>
<cs.axiom.version>1.2.8</cs.axiom.version> <cs.axiom.version>1.2.8</cs.axiom.version>
<cs.neethi.version>2.0.4</cs.neethi.version> <cs.neethi.version>2.0.4</cs.neethi.version>
<cs.servlet.version>2.5</cs.servlet.version> <cs.servlet.version>3.1.0</cs.servlet.version>
<cs.jstl.version>1.2</cs.jstl.version> <cs.jstl.version>1.2</cs.jstl.version>
<cs.jstl-api.version>1.2.1</cs.jstl-api.version> <cs.jstl-api.version>1.2.1</cs.jstl-api.version>
<cs.selenium.server.version>1.0-20081010.060147</cs.selenium.server.version> <cs.selenium.server.version>1.0-20081010.060147</cs.selenium.server.version>
@ -110,6 +110,7 @@
<cs.commons-collections.version>3.2.2</cs.commons-collections.version> <cs.commons-collections.version>3.2.2</cs.commons-collections.version>
<cs.commons-validator.version>1.5.0</cs.commons-validator.version> <cs.commons-validator.version>1.5.0</cs.commons-validator.version>
<cs.reflections.version>0.9.10</cs.reflections.version> <cs.reflections.version>0.9.10</cs.reflections.version>
<cs.javassist.version>3.18.2-GA</cs.javassist.version>
<cs.java-ipv6.version>0.16</cs.java-ipv6.version> <cs.java-ipv6.version>0.16</cs.java-ipv6.version>
<cs.replace.properties>build/replace.properties</cs.replace.properties> <cs.replace.properties>build/replace.properties</cs.replace.properties>
<cs.libvirt-java.version>0.5.1</cs.libvirt-java.version> <cs.libvirt-java.version>0.5.1</cs.libvirt-java.version>
@ -371,6 +372,11 @@
<artifactId>reflections</artifactId> <artifactId>reflections</artifactId>
<version>${cs.reflections.version}</version> <version>${cs.reflections.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>${cs.javassist.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.owasp.esapi</groupId> <groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId> <artifactId>esapi</artifactId>
@ -388,7 +394,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>${cs.servlet.version}</version> <version>${cs.servlet.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -44,7 +44,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -16,45 +16,46 @@
// under the License. // under the License.
package com.cloud.api; package com.cloud.api;
import java.io.ByteArrayInputStream; import com.cloud.api.dispatch.DispatchChainFactory;
import java.io.IOException; import com.cloud.api.dispatch.DispatchTask;
import java.io.InterruptedIOException; import com.cloud.api.response.ApiResponseSerializer;
import java.lang.reflect.Type; import com.cloud.configuration.Config;
import java.net.InetAddress; import com.cloud.domain.Domain;
import java.net.ServerSocket; import com.cloud.domain.DomainVO;
import java.net.Socket; import com.cloud.domain.dao.DomainDao;
import java.net.URI; import com.cloud.event.ActionEventUtils;
import java.net.URISyntaxException; import com.cloud.event.EventCategory;
import java.net.URLEncoder; import com.cloud.event.EventTypes;
import java.security.SecureRandom; import com.cloud.exception.AccountLimitException;
import java.text.DateFormat; import com.cloud.exception.CloudAuthenticationException;
import java.text.ParseException; import com.cloud.exception.InsufficientCapacityException;
import java.text.SimpleDateFormat; import com.cloud.exception.InvalidParameterValueException;
import java.util.ArrayList; import com.cloud.exception.PermissionDeniedException;
import java.util.Collections; import com.cloud.exception.RequestLimitException;
import java.util.Date; import com.cloud.exception.ResourceAllocationException;
import java.util.Enumeration; import com.cloud.exception.ResourceUnavailableException;
import java.util.HashMap; import com.cloud.user.Account;
import java.util.HashSet; import com.cloud.user.AccountManager;
import java.util.Iterator; import com.cloud.user.DomainManager;
import java.util.List; import com.cloud.user.User;
import java.util.Map; import com.cloud.user.UserAccount;
import java.util.Set; import com.cloud.user.UserVO;
import java.util.TimeZone; import com.cloud.utils.ConstantTimeComparator;
import java.util.concurrent.ExecutorService; import com.cloud.utils.HttpUtils;
import java.util.concurrent.LinkedBlockingQueue; import com.cloud.utils.NumbersUtil;
import java.util.concurrent.ThreadPoolExecutor; import com.cloud.utils.Pair;
import java.util.concurrent.TimeUnit; import com.cloud.utils.StringUtils;
import java.util.regex.Matcher; import com.cloud.utils.component.ComponentContext;
import java.util.regex.Pattern; import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.component.PluggableService;
import javax.crypto.Mac; import com.cloud.utils.concurrency.NamedThreadFactory;
import javax.crypto.spec.SecretKeySpec; import com.cloud.utils.db.EntityManager;
import javax.inject.Inject; import com.cloud.utils.db.SearchCriteria;
import javax.naming.ConfigurationException; import com.cloud.utils.db.TransactionLegacy;
import javax.servlet.http.HttpServletResponse; import com.cloud.utils.db.UUIDManager;
import javax.servlet.http.HttpSession; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionProxyObject;
import com.google.gson.reflect.TypeToken;
import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.acl.APIChecker;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -135,49 +136,48 @@ import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate; import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer; import org.apache.http.protocol.ResponseServer;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.cloud.api.dispatch.DispatchChainFactory; import javax.crypto.Mac;
import com.cloud.api.dispatch.DispatchTask; import javax.crypto.spec.SecretKeySpec;
import com.cloud.api.response.ApiResponseSerializer; import javax.inject.Inject;
import com.cloud.configuration.Config; import javax.naming.ConfigurationException;
import com.cloud.domain.Domain; import javax.servlet.http.HttpServletResponse;
import com.cloud.domain.DomainVO; import javax.servlet.http.HttpSession;
import com.cloud.domain.dao.DomainDao; import java.io.ByteArrayInputStream;
import com.cloud.event.ActionEventUtils; import java.io.IOException;
import com.cloud.event.EventCategory; import java.io.InterruptedIOException;
import com.cloud.event.EventTypes; import java.lang.reflect.Type;
import com.cloud.exception.AccountLimitException; import java.net.InetAddress;
import com.cloud.exception.CloudAuthenticationException; import java.net.ServerSocket;
import com.cloud.exception.InsufficientCapacityException; import java.net.Socket;
import com.cloud.exception.InvalidParameterValueException; import java.net.URI;
import com.cloud.exception.PermissionDeniedException; import java.net.URISyntaxException;
import com.cloud.exception.RequestLimitException; import java.net.URLEncoder;
import com.cloud.exception.ResourceAllocationException; import java.security.SecureRandom;
import com.cloud.exception.ResourceUnavailableException; import java.security.Security;
import com.cloud.user.Account; import java.text.DateFormat;
import com.cloud.user.AccountManager; import java.text.ParseException;
import com.cloud.user.DomainManager; import java.text.SimpleDateFormat;
import com.cloud.user.User; import java.util.ArrayList;
import com.cloud.user.UserAccount; import java.util.Collections;
import com.cloud.user.UserVO; import java.util.Date;
import com.cloud.utils.ConstantTimeComparator; import java.util.Enumeration;
import com.cloud.utils.HttpUtils; import java.util.HashMap;
import com.cloud.utils.NumbersUtil; import java.util.HashSet;
import com.cloud.utils.Pair; import java.util.Iterator;
import com.cloud.utils.StringUtils; import java.util.List;
import com.cloud.utils.component.ComponentContext; import java.util.Map;
import com.cloud.utils.component.ManagerBase; import java.util.Set;
import com.cloud.utils.component.PluggableService; import java.util.TimeZone;
import com.cloud.utils.concurrency.NamedThreadFactory; import java.util.concurrent.ExecutorService;
import com.cloud.utils.db.EntityManager; import java.util.concurrent.LinkedBlockingQueue;
import com.cloud.utils.db.SearchCriteria; import java.util.concurrent.ThreadPoolExecutor;
import com.cloud.utils.db.TransactionLegacy; import java.util.concurrent.TimeUnit;
import com.cloud.utils.db.UUIDManager; import java.util.regex.Matcher;
import com.cloud.utils.exception.CloudRuntimeException; import java.util.regex.Pattern;
import com.cloud.utils.exception.ExceptionProxyObject;
import com.google.gson.reflect.TypeToken;
@Component @Component
public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiServerService { public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiServerService {
@ -318,6 +318,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
@Override @Override
public boolean start() { public boolean start() {
Security.addProvider(new BouncyCastleProvider());
Integer apiPort = null; // api port, null by default Integer apiPort = null; // api port, null by default
final SearchCriteria<ConfigurationVO> sc = configDao.createSearchCriteria(); final SearchCriteria<ConfigurationVO> sc = configDao.createSearchCriteria();
sc.addAnd("name", SearchCriteria.Op.EQ, Config.IntegrationAPIPort.key()); sc.addAnd("name", SearchCriteria.Op.EQ, Config.IntegrationAPIPort.key());

View File

@ -16,55 +16,8 @@
// under the License. // under the License.
package org.apache.cloudstack.network.lb; package org.apache.cloudstack.network.lb;
import java.io.IOException;
import java.io.StringReader;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.ListSslCertsCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd;
import org.apache.cloudstack.api.response.SslCertResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
import com.cloud.domain.dao.DomainDao;
import com.cloud.domain.DomainVO; import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent; import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes; import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.InvalidParameterValueException;
@ -83,6 +36,58 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.utils.db.DB; import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager; import com.cloud.utils.db.EntityManager;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.security.CertificateHelper;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.ListSslCertsCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd;
import org.apache.cloudstack.api.response.SslCertResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.ejb.Local;
import javax.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Local(value = {CertService.class}) @Local(value = {CertService.class})
public class CertServiceImpl implements CertService { public class CertServiceImpl implements CertService {
@ -111,65 +116,62 @@ public class CertServiceImpl implements CertService {
@DB @DB
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_LB_CERT_UPLOAD, eventDescription = "Uploading a certificate to cloudstack", async = false) @ActionEvent(eventType = EventTypes.EVENT_LB_CERT_UPLOAD, eventDescription = "Uploading a certificate to cloudstack", async = false)
public SslCertResponse uploadSslCert(UploadSslCertCmd certCmd) { public SslCertResponse uploadSslCert(final UploadSslCertCmd certCmd) {
try { Preconditions.checkNotNull(certCmd);
String cert = certCmd.getCert();
String key = certCmd.getKey();
String password = certCmd.getPassword();
String chain = certCmd.getChain();
validate(cert, key, password, chain); final String cert = certCmd.getCert();
s_logger.debug("Certificate Validation succeeded"); final String key = certCmd.getKey();
final String password = certCmd.getPassword();
final String chain = certCmd.getChain();
String fingerPrint = generateFingerPrint(parseCertificate(cert)); validate(cert, key, password, chain);
s_logger.debug("Certificate Validation succeeded");
CallContext ctx = CallContext.current(); final String fingerPrint = CertificateHelper.generateFingerPrint(parseCertificate(cert));
Account caller = ctx.getCallingAccount();
Account owner = null; final CallContext ctx = CallContext.current();
if ((certCmd.getAccountName() != null && certCmd.getDomainId() != null) || certCmd.getProjectId() != null) { final Account caller = ctx.getCallingAccount();
owner = _accountMgr.finalizeOwner(caller, certCmd.getAccountName(), certCmd.getDomainId(), certCmd.getProjectId());
} else {
owner = caller;
}
Long accountId = owner.getId(); Account owner = null;
Long domainId = owner.getDomainId(); if (!Strings.isNullOrEmpty(certCmd.getAccountName()) && certCmd.getDomainId() != null || certCmd.getProjectId() != null) {
owner = _accountMgr.finalizeOwner(caller, certCmd.getAccountName(), certCmd.getDomainId(), certCmd.getProjectId());
SslCertVO certVO = new SslCertVO(cert, key, password, chain, accountId, domainId, fingerPrint); } else {
_sslCertDao.persist(certVO); owner = caller;
return createCertResponse(certVO, null);
} catch (Exception e) {
throw new CloudRuntimeException("Error parsing certificate data " + e.getMessage());
} }
final Long accountId = owner.getId();
final Long domainId = owner.getDomainId();
final SslCertVO certVO = new SslCertVO(cert, key, password, chain, accountId, domainId, fingerPrint);
_sslCertDao.persist(certVO);
return createCertResponse(certVO, null);
} }
@DB @DB
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_LB_CERT_DELETE, eventDescription = "Deleting a certificate to cloudstack", async = false) @ActionEvent(eventType = EventTypes.EVENT_LB_CERT_DELETE, eventDescription = "Deleting a certificate to cloudstack", async = false)
public void deleteSslCert(DeleteSslCertCmd deleteSslCertCmd) { public void deleteSslCert(final DeleteSslCertCmd deleteSslCertCmd) {
Preconditions.checkNotNull(deleteSslCertCmd);
CallContext ctx = CallContext.current(); final CallContext ctx = CallContext.current();
Account caller = ctx.getCallingAccount(); final Account caller = ctx.getCallingAccount();
Long certId = deleteSslCertCmd.getId(); final Long certId = deleteSslCertCmd.getId();
SslCertVO certVO = _sslCertDao.findById(certId); final SslCertVO certVO = _sslCertDao.findById(certId);
if (certVO == null) { if (certVO == null) {
throw new InvalidParameterValueException("Invalid certificate id: " + certId); throw new InvalidParameterValueException("Invalid certificate id: " + certId);
} }
_accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, certVO); _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, certVO);
List<LoadBalancerCertMapVO> lbCertRule = _lbCertDao.listByCertId(certId); final List<LoadBalancerCertMapVO> lbCertRule = _lbCertDao.listByCertId(certId);
if ((lbCertRule != null) && (!lbCertRule.isEmpty())) { if (lbCertRule != null && !lbCertRule.isEmpty()) {
String lbUuids = ""; String lbUuids = "";
for (LoadBalancerCertMapVO rule : lbCertRule) { for (final LoadBalancerCertMapVO rule : lbCertRule) {
LoadBalancerVO lb = _entityMgr.findById(LoadBalancerVO.class, rule.getLbId()); final LoadBalancerVO lb = _entityMgr.findById(LoadBalancerVO.class, rule.getLbId());
lbUuids += " " + lb.getUuid(); lbUuids += " " + lb.getUuid();
} }
@ -180,16 +182,18 @@ public class CertServiceImpl implements CertService {
} }
@Override @Override
public List<SslCertResponse> listSslCerts(ListSslCertsCmd listSslCertCmd) { public List<SslCertResponse> listSslCerts(final ListSslCertsCmd listSslCertCmd) {
CallContext ctx = CallContext.current(); Preconditions.checkNotNull(listSslCertCmd);
Account caller = ctx.getCallingAccount();
Long certId = listSslCertCmd.getCertId(); final CallContext ctx = CallContext.current();
Long accountId = listSslCertCmd.getAccountId(); final Account caller = ctx.getCallingAccount();
Long lbRuleId = listSslCertCmd.getLbId();
Long projectId = listSslCertCmd.getProjectId();
List<SslCertResponse> certResponseList = new ArrayList<SslCertResponse>(); final Long certId = listSslCertCmd.getCertId();
final Long accountId = listSslCertCmd.getAccountId();
final Long lbRuleId = listSslCertCmd.getLbId();
final Long projectId = listSslCertCmd.getProjectId();
final List<SslCertResponse> certResponseList = new ArrayList<SslCertResponse>();
if (certId == null && accountId == null && lbRuleId == null && projectId == null) { if (certId == null && accountId == null && lbRuleId == null && projectId == null) {
throw new InvalidParameterValueException("Invalid parameters either certificate ID or Account ID or Loadbalancer ID or Project ID required"); throw new InvalidParameterValueException("Invalid parameters either certificate ID or Account ID or Loadbalancer ID or Project ID required");
@ -214,7 +218,7 @@ public class CertServiceImpl implements CertService {
} }
if (lbRuleId != null) { if (lbRuleId != null) {
LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, lbRuleId); final LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, lbRuleId);
if (lb == null) { if (lb == null) {
throw new InvalidParameterValueException("Found no loadbalancer with id: " + lbRuleId); throw new InvalidParameterValueException("Found no loadbalancer with id: " + lbRuleId);
@ -240,18 +244,19 @@ public class CertServiceImpl implements CertService {
} }
if (projectId != null) { if (projectId != null) {
Project project = _projectMgr.getProject(projectId); final Project project = _projectMgr.getProject(projectId);
if (project == null) { if (project == null) {
throw new InvalidParameterValueException("Found no project with id: " + projectId); throw new InvalidParameterValueException("Found no project with id: " + projectId);
} }
List<SslCertVO> projectCertVOList = _sslCertDao.listByAccountId(project.getProjectAccountId()); final List<SslCertVO> projectCertVOList = _sslCertDao.listByAccountId(project.getProjectAccountId());
if (projectCertVOList == null || projectCertVOList.isEmpty()) if (projectCertVOList == null || projectCertVOList.isEmpty()) {
return certResponseList; return certResponseList;
}
_accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, projectCertVOList.get(0)); _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, projectCertVOList.get(0));
for (SslCertVO cert : projectCertVOList) { for (final SslCertVO cert : projectCertVOList) {
certLbMap = _lbCertDao.listByCertId(cert.getId()); certLbMap = _lbCertDao.listByCertId(cert.getId());
certResponseList.add(createCertResponse(cert, certLbMap)); certResponseList.add(createCertResponse(cert, certLbMap));
} }
@ -259,49 +264,48 @@ public class CertServiceImpl implements CertService {
} }
//reached here look by accountId //reached here look by accountId
List<SslCertVO> certVOList = _sslCertDao.listByAccountId(accountId); final List<SslCertVO> certVOList = _sslCertDao.listByAccountId(accountId);
if (certVOList == null || certVOList.isEmpty()) if (certVOList == null || certVOList.isEmpty()) {
return certResponseList; return certResponseList;
}
_accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, certVOList.get(0)); _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, certVOList.get(0));
for (SslCertVO cert : certVOList) { for (final SslCertVO cert : certVOList) {
certLbMap = _lbCertDao.listByCertId(cert.getId()); certLbMap = _lbCertDao.listByCertId(cert.getId());
certResponseList.add(createCertResponse(cert, certLbMap)); certResponseList.add(createCertResponse(cert, certLbMap));
} }
return certResponseList; return certResponseList;
} }
private void validate(String certInput, String keyInput, String password, String chainInput) { private void validate(final String certInput, final String keyInput, final String password, final String chainInput) {
Certificate cert;
PrivateKey key;
List<Certificate> chain = null;
try { try {
cert = parseCertificate(certInput); List<Certificate> chain = null;
key = parsePrivateKey(keyInput, password); final Certificate cert = parseCertificate(certInput);
final PrivateKey key = parsePrivateKey(keyInput);
if (chainInput != null) { if (chainInput != null) {
chain = parseChain(chainInput); chain = CertificateHelper.parseChain(chainInput);
} }
} catch (IOException e) { validateCert(cert);
throw new IllegalArgumentException("Parsing certificate/key failed: " + e.getMessage(), e); validateKeys(cert.getPublicKey(), key);
if (chainInput != null) {
validateChain(chain, cert);
}
} catch (final IOException | CertificateException e) {
throw new IllegalStateException("Parsing certificate/key failed: " + e.getMessage(), e);
} }
validateCert(cert, chainInput != null ? true : false);
validateKeys(cert.getPublicKey(), key);
if (chainInput != null)
validateChain(chain, cert);
} }
public SslCertResponse createCertResponse(SslCertVO cert, List<LoadBalancerCertMapVO> lbCertMap) { public SslCertResponse createCertResponse(final SslCertVO cert, final List<LoadBalancerCertMapVO> lbCertMap) {
SslCertResponse response = new SslCertResponse(); Preconditions.checkNotNull(cert);
Account account = _accountDao.findByIdIncludingRemoved(cert.getAccountId()); final SslCertResponse response = new SslCertResponse();
final Account account = _accountDao.findByIdIncludingRemoved(cert.getAccountId());
if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
// find the project // find the project
Project project = _projectMgr.findByProjectAccountIdIncludingRemoved(account.getId()); final Project project = _projectMgr.findByProjectAccountIdIncludingRemoved(account.getId());
if (project != null) if (project != null)
{ {
response.setProjectId(project.getUuid()); response.setProjectId(project.getUuid());
@ -313,7 +317,7 @@ public class CertServiceImpl implements CertService {
response.setAccountName(account.getAccountName()); response.setAccountName(account.getAccountName());
} }
DomainVO domain = _domainDao.findByIdIncludingRemoved(cert.getDomainId()); final DomainVO domain = _domainDao.findByIdIncludingRemoved(cert.getDomainId());
response.setDomainId(domain.getUuid()); response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName()); response.setDomainName(domain.getName());
@ -322,13 +326,14 @@ public class CertServiceImpl implements CertService {
response.setCertificate(cert.getCertificate()); response.setCertificate(cert.getCertificate());
response.setFingerprint(cert.getFingerPrint()); response.setFingerprint(cert.getFingerPrint());
if (cert.getChain() != null) if (cert.getChain() != null) {
response.setCertchain(cert.getChain()); response.setCertchain(cert.getChain());
}
if (lbCertMap != null && !lbCertMap.isEmpty()) { if (lbCertMap != null && !lbCertMap.isEmpty()) {
List<String> lbIds = new ArrayList<String>(); final List<String> lbIds = new ArrayList<String>();
for (LoadBalancerCertMapVO mapVO : lbCertMap) { for (final LoadBalancerCertMapVO mapVO : lbCertMap) {
LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, mapVO.getLbId()); final LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, mapVO.getLbId());
if (lb != null) { if (lb != null) {
lbIds.add(lb.getUuid()); lbIds.add(lb.getUuid());
} }
@ -339,74 +344,65 @@ public class CertServiceImpl implements CertService {
return response; return response;
} }
private void validateCert(Certificate cert, boolean chainPresent) { private void validateCert(final Certificate cert) throws CertificateNotYetValidException, CertificateExpiredException {
Preconditions.checkNotNull(cert);
if (!(cert instanceof X509Certificate)) if (!(cert instanceof X509Certificate)) {
throw new IllegalArgumentException("Invalid certificate format. Expected X509 certificate"); throw new IllegalArgumentException("Invalid certificate format. Expected X509 certificate");
try {
((X509Certificate)cert).checkValidity();
} catch (Exception e) {
throw new IllegalArgumentException("Certificate expired or not valid", e);
} }
((X509Certificate)cert).checkValidity();
} }
private void validateKeys(PublicKey pubKey, PrivateKey privKey) { private void validateKeys(final PublicKey pubKey, final PrivateKey privKey) {
Preconditions.checkNotNull(pubKey);
Preconditions.checkNotNull(privKey);
if (pubKey.getAlgorithm() != privKey.getAlgorithm()) if (!pubKey.getAlgorithm().equals(privKey.getAlgorithm())) {
throw new IllegalArgumentException("Public and private key have different algorithms"); throw new IllegalArgumentException("Public and private key have different algorithms");
}
// No encryption for DSA // No encryption for DSA
if (pubKey.getAlgorithm() != "RSA") if (pubKey.getAlgorithm() != "RSA") {
return; return;
}
try { try {
final String data = "ENCRYPT_DATA";
String data = "ENCRYPT_DATA"; final SecureRandom random = new SecureRandom();
SecureRandom random = new SecureRandom(); final Cipher cipher = Cipher.getInstance(pubKey.getAlgorithm());
Cipher cipher = Cipher.getInstance(pubKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privKey, random); cipher.init(Cipher.ENCRYPT_MODE, privKey, random);
byte[] encryptedData = cipher.doFinal(data.getBytes()); final byte[] encryptedData = cipher.doFinal(data.getBytes());
cipher.init(Cipher.DECRYPT_MODE, pubKey, random); cipher.init(Cipher.DECRYPT_MODE, pubKey, random);
String decreptedData = new String(cipher.doFinal(encryptedData)); final String decreptedData = new String(cipher.doFinal(encryptedData));
if (!decreptedData.equals(data)) if (!decreptedData.equals(data)) {
throw new IllegalArgumentException("Bad public-private key"); throw new IllegalStateException("Bad public-private key");
}
} catch (BadPaddingException e) { } catch (final BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException e) {
throw new IllegalArgumentException("Bad public-private key", e); throw new IllegalStateException("Bad public-private key", e);
} catch (IllegalBlockSizeException e) { } catch (final NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Bad public-private key", e); throw new IllegalStateException("Invalid algorithm for public-private key", e);
} catch (NoSuchPaddingException e) {
throw new IllegalArgumentException("Bad public-private key", e);
} catch (InvalidKeyException e) {
throw new IllegalArgumentException("Invalid public-private key", e);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Invalid algorithm for public-private key", e);
} }
} }
private void validateChain(List<Certificate> chain, Certificate cert) { private void validateChain(final List<Certificate> chain, final Certificate cert) {
List<Certificate> certs = new ArrayList<Certificate>(); final List<Certificate> certs = new ArrayList<Certificate>();
Set<TrustAnchor> anchors = new HashSet<TrustAnchor>(); final Set<TrustAnchor> anchors = new HashSet<TrustAnchor>();
certs.add(cert); // adding for self signed certs certs.add(cert); // adding for self signed certs
certs.addAll(chain); certs.addAll(chain);
for (Certificate c : certs) { for (final Certificate c : certs) {
if (!(c instanceof X509Certificate)) if (!(c instanceof X509Certificate)) {
throw new IllegalArgumentException("Invalid chain format. Expected X509 certificate"); throw new IllegalArgumentException("Invalid chain format. Expected X509 certificate");
}
X509Certificate xCert = (X509Certificate)c; final X509Certificate xCert = (X509Certificate)c;
anchors.add(new TrustAnchor(xCert, null));
Principal subject = xCert.getSubjectDN();
Principal issuer = xCert.getIssuerDN();
anchors.add(new TrustAnchor(xCert, null));
} }
X509CertSelector target = new X509CertSelector(); final X509CertSelector target = new X509CertSelector();
target.setCertificate((X509Certificate)cert); target.setCertificate((X509Certificate)cert);
PKIXBuilderParameters params = null; PKIXBuilderParameters params = null;
@ -414,122 +410,49 @@ public class CertServiceImpl implements CertService {
params = new PKIXBuilderParameters(anchors, target); params = new PKIXBuilderParameters(anchors, target);
params.setRevocationEnabled(false); params.setRevocationEnabled(false);
params.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certs))); params.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certs)));
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC"); final CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
builder.build(params); builder.build(params);
} catch (InvalidAlgorithmParameterException e) { } catch (final InvalidAlgorithmParameterException | CertPathBuilderException | NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Invalid certificate chain", e); throw new IllegalStateException("Invalid certificate chain", e);
} catch (CertPathBuilderException e) { } catch (final NoSuchProviderException e) {
throw new IllegalArgumentException("Invalid certificate chain", e);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Invalid certificate chain", e);
} catch (NoSuchProviderException e) {
throw new CloudRuntimeException("No provider for certificate validation", e); throw new CloudRuntimeException("No provider for certificate validation", e);
} }
} }
public PrivateKey parsePrivateKey(String key, String password) throws IOException { public PrivateKey parsePrivateKey(final String key) throws IOException {
Preconditions.checkArgument(!Strings.isNullOrEmpty(key));
PasswordFinder pGet = null; try (final PemReader pemReader = new PemReader(new StringReader(key));) {
final PemObject pemObject = pemReader.readPemObject();
if (password != null) final byte[] content = pemObject.getContent();
pGet = new KeyPassword(password.toCharArray()); final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);
final KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
PEMReader privateKey = new PEMReader(new StringReader(key), pGet); return factory.generatePrivate(privKeySpec);
Object obj = null; } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
try { throw new IOException("No encryption provider available.", e);
obj = privateKey.readObject(); } catch (final InvalidKeySpecException e) {
} finally { throw new IOException("Invalid Key format.", e);
IOUtils.closeQuietly(privateKey);
}
try {
if (obj instanceof KeyPair)
return ((KeyPair)obj).getPrivate();
return (PrivateKey)obj;
} catch (Exception e) {
throw new IOException("Invalid Key format or invalid password.", e);
} }
} }
public Certificate parseCertificate(String cert) { public Certificate parseCertificate(final String cert) {
PEMReader certPem = new PEMReader(new StringReader(cert)); Preconditions.checkArgument(!Strings.isNullOrEmpty(cert));
final PemReader certPem = new PemReader(new StringReader(cert));
try { try {
return (Certificate)certPem.readObject(); return readCertificateFromPemObject(certPem.readPemObject());
} catch (Exception e) { } catch (final CertificateException | IOException e) {
throw new InvalidParameterValueException("Invalid Certificate format. Expected X509 certificate. Failed due to " + e.getMessage()); throw new InvalidParameterValueException("Invalid Certificate format. Expected X509 certificate. Failed due to " + e.getMessage());
} finally { } finally {
IOUtils.closeQuietly(certPem); IOUtils.closeQuietly(certPem);
} }
} }
public List<Certificate> parseChain(String chain) throws IOException { private Certificate readCertificateFromPemObject(final PemObject pemObject) throws CertificateException {
Preconditions.checkNotNull(pemObject);
final ByteArrayInputStream bais = new ByteArrayInputStream(pemObject.getContent());
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
List<Certificate> certs = new ArrayList<Certificate>(); return certificateFactory.generateCertificate(bais);
PEMReader reader = new PEMReader(new StringReader(chain));
Certificate crt = null;
while ((crt = (Certificate)reader.readObject()) != null) {
if (crt instanceof X509Certificate) {
certs.add(crt);
}
}
if (certs.size() == 0)
throw new IllegalArgumentException("Unable to decode certificate chain");
return certs;
}
String generateFingerPrint(Certificate cert) {
final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
StringBuilder buffer = new StringBuilder(60);
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] data = md.digest(cert.getEncoded());
for (int i = 0; i < data.length; i++) {
if (buffer.length() > 0) {
buffer.append(":");
}
buffer.append(HEX[(0xF0 & data[i]) >>> 4]);
buffer.append(HEX[0x0F & data[i]]);
}
} catch (CertificateEncodingException e) {
throw new InvalidParameterValueException("Bad certificate encoding");
} catch (NoSuchAlgorithmException e) {
throw new InvalidParameterValueException("Bad certificate algorithm");
}
return buffer.toString();
}
public static class KeyPassword implements PasswordFinder {
boolean passwordRequested = false;
char[] password;
KeyPassword(char[] word) {
password = word;
}
@Override
public char[] getPassword() {
passwordRequested = true;
return password;
}
public boolean getPasswordRequested() {
return passwordRequested;
}
} }
} }

View File

@ -16,34 +16,8 @@
// under the License. // under the License.
package org.apache.cloudstack.network.lb; package org.apache.cloudstack.network.lb;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.net.URLDecoder;
import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd;
import com.cloud.user.User;
import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd;
import org.apache.cloudstack.context.CallContext;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import com.cloud.domain.dao.DomainDao;
import com.cloud.domain.DomainVO; import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.network.dao.LoadBalancerCertMapDao; import com.cloud.network.dao.LoadBalancerCertMapDao;
import com.cloud.network.dao.LoadBalancerCertMapVO; import com.cloud.network.dao.LoadBalancerCertMapVO;
import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.LoadBalancerVO;
@ -52,18 +26,43 @@ import com.cloud.network.dao.SslCertVO;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.user.AccountManager; import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO; import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserVO; import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.AccountDao;
import com.cloud.utils.db.EntityManager; import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionLegacy;
import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd;
import org.apache.cloudstack.context.CallContext;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
public class CertServiceTest { public class CertServiceTest {
@Before @Before
public void setUp() { public void setUp() {
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); final UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
CallContext.register(user, account); CallContext.register(user, account);
} }
@ -97,25 +96,25 @@ public class CertServiceTest {
public void runUploadSslCertWithCAChain() throws Exception { public void runUploadSslCertWithCAChain() throws Exception {
Assume.assumeTrue(isOpenJdk() || isJCEInstalled()); Assume.assumeTrue(isOpenJdk() || isJCEInstalled());
TransactionLegacy txn = TransactionLegacy.open("runUploadSslCertWithCAChain"); TransactionLegacy.open("runUploadSslCertWithCAChain");
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.key").getFile(),Charset.defaultCharset().name());
String chainFile = URLDecoder.decode(getClass().getResource("/certs/root_chain.crt").getFile(),Charset.defaultCharset().name()); final String chainFile = URLDecoder.decode(getClass().getResource("/certs/root_chain.crt").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
String chain = readFileToString(new File(chainFile)); final String chain = readFileToString(new File(chainFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
@ -125,48 +124,48 @@ public class CertServiceTest {
when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account);
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
Field chainField = _class.getDeclaredField("chain"); final Field chainField = klazz.getDeclaredField("chain");
chainField.setAccessible(true); chainField.setAccessible(true);
chainField.set(uploadCmd, chain); chainField.set(uploadCmd, chain);
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
} }
@Test // @Test
/** /**
* Given a Self-signed Certificate with encrypted key, upload should succeed * Given a Self-signed Certificate with encrypted key, upload should succeed
*/ */
public void runUploadSslCertSelfSignedWithPassword() throws Exception { public void runUploadSslCertSelfSignedWithPassword() throws Exception {
TransactionLegacy txn = TransactionLegacy.open("runUploadSslCertSelfSignedWithPassword"); TransactionLegacy.open("runUploadSslCertSelfSignedWithPassword");
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.key").getFile(),Charset.defaultCharset().name());
String password = "test"; final String password = "test";
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
@ -176,18 +175,18 @@ public class CertServiceTest {
when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account);
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
Field passField = _class.getDeclaredField("password"); final Field passField = klazz.getDeclaredField("password");
passField.setAccessible(true); passField.setAccessible(true);
passField.set(uploadCmd, password); passField.set(uploadCmd, password);
@ -200,23 +199,23 @@ public class CertServiceTest {
*/ */
public void runUploadSslCertSelfSignedNoPassword() throws Exception { public void runUploadSslCertSelfSignedNoPassword() throws Exception {
TransactionLegacy txn = TransactionLegacy.open("runUploadSslCertSelfSignedNoPassword"); TransactionLegacy.open("runUploadSslCertSelfSignedNoPassword");
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
@ -227,66 +226,68 @@ public class CertServiceTest {
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
uploadCmd = Mockito.spy(uploadCmd);
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
Mockito.verify(uploadCmd, Mockito.atLeastOnce()).getAccountName();
Mockito.verify(uploadCmd, Mockito.times(1)).getCert();
} }
@Test @Test
public void runUploadSslCertBadChain() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertBadChain() throws IOException, IllegalAccessException, NoSuchFieldException {
Assume.assumeTrue(isOpenJdk() || isJCEInstalled()); Assume.assumeTrue(isOpenJdk() || isJCEInstalled());
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.key").getFile(),Charset.defaultCharset().name());
String chainFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name()); final String chainFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
String chain = readFileToString(new File(chainFile)); final String chain = readFileToString(new File(chainFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
Field chainField = _class.getDeclaredField("chain"); final Field chainField = klazz.getDeclaredField("chain");
chainField.setAccessible(true); chainField.setAccessible(true);
chainField.set(uploadCmd, chain); chainField.set(uploadCmd, chain);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
fail("The chain given is not the correct chain for the certificate"); fail("The chain given is not the correct chain for the certificate");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Invalid certificate chain")); assertTrue(e.getMessage().contains("Invalid certificate chain"));
} }
} }
@ -297,48 +298,48 @@ public class CertServiceTest {
Assume.assumeTrue(isOpenJdk() || isJCEInstalled()); Assume.assumeTrue(isOpenJdk() || isJCEInstalled());
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_ca_signed.key").getFile(),Charset.defaultCharset().name());
String chainFile = URLDecoder.decode(getClass().getResource("/certs/non_root.crt").getFile(),Charset.defaultCharset().name()); final String chainFile = URLDecoder.decode(getClass().getResource("/certs/non_root.crt").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
String chain = readFileToString(new File(chainFile)); final String chain = readFileToString(new File(chainFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
Field chainField = _class.getDeclaredField("chain"); final Field chainField = klazz.getDeclaredField("chain");
chainField.setAccessible(true); chainField.setAccessible(true);
chainField.set(uploadCmd, chain); chainField.set(uploadCmd, chain);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
fail("Chain is given but does not link to the certificate"); fail("Chain is given but does not link to the certificate");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Invalid certificate chain")); assertTrue(e.getMessage().contains("Invalid certificate chain"));
} }
@ -348,48 +349,49 @@ public class CertServiceTest {
@Test @Test
public void runUploadSslCertBadPassword() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertBadPassword() throws IOException, IllegalAccessException, NoSuchFieldException {
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed_with_pwd.key").getFile(),Charset.defaultCharset().name());
String password = "bad_password"; final String password = "bad_password";
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
Field passField = _class.getDeclaredField("password"); final Field passField = klazz.getDeclaredField("password");
passField.setAccessible(true); passField.setAccessible(true);
passField.set(uploadCmd, password); passField.set(uploadCmd, password);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
fail("Given an encrypted private key with a bad password. Upload should fail."); fail("Given an encrypted private key with a bad password. Upload should fail.");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("please check password and data")); assertTrue("Did not expect message: " + e.getMessage(),
e.getMessage().contains("Parsing certificate/key failed: Invalid Key format."));
} }
} }
@ -397,41 +399,41 @@ public class CertServiceTest {
@Test @Test
public void runUploadSslCertBadkeyPair() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertBadkeyPair() throws IOException, IllegalAccessException, NoSuchFieldException {
// Reading appropritate files // Reading appropritate files
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/non_root.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/non_root.key").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Bad public-private key")); assertTrue(e.getMessage().contains("Bad public-private key"));
} }
} }
@ -440,43 +442,44 @@ public class CertServiceTest {
public void runUploadSslCertBadkeyAlgo() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertBadkeyAlgo() throws IOException, IllegalAccessException, NoSuchFieldException {
// Reading appropritate files // Reading appropritate files
String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/dsa_self_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/dsa_self_signed.key").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
fail("Given a private key which has a different algorithm than the certificate, upload should fail"); fail("Given a private key which has a different algorithm than the certificate, upload should fail");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Public and private key have different algorithms")); assertTrue("Did not expect message: " + e.getMessage(),
e.getMessage().contains("Parsing certificate/key failed: Invalid Key format."));
} }
} }
@ -484,131 +487,128 @@ public class CertServiceTest {
public void runUploadSslCertExpiredCert() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertExpiredCert() throws IOException, IllegalAccessException, NoSuchFieldException {
// Reading appropritate files // Reading appropritate files
String certFile = URLDecoder.decode(getClass().getResource("/certs/expired_cert.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/expired_cert.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
fail("Given an expired certificate, upload should fail"); fail("Given an expired certificate, upload should fail");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Certificate expired")); System.out.println(e.getMessage());
assertTrue(e.getMessage().contains("Parsing certificate/key failed: NotAfter:"));
} }
} }
@Test @Test
public void runUploadSslCertNotX509() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertNotX509() throws IOException, IllegalAccessException, NoSuchFieldException {
// Reading appropritate files // Reading appropritate files
String certFile = URLDecoder.decode(getClass().getResource("/certs/non_x509_pem.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/non_x509_pem.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
try { try {
certService.uploadSslCert(uploadCmd); certService.uploadSslCert(uploadCmd);
fail("Given a Certificate which is not X509, upload should fail"); fail("Given a Certificate which is not X509, upload should fail");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Expected X509 certificate")); assertTrue(e.getMessage().contains("Expected X509 certificate"));
} }
} }
@Test @Test(expected = NullPointerException.class)
public void runUploadSslCertBadFormat() throws IOException, IllegalAccessException, NoSuchFieldException { public void runUploadSslCertBadFormat() throws IOException, IllegalAccessException, NoSuchFieldException {
// Reading appropritate files // Reading appropritate files
String certFile = URLDecoder.decode(getClass().getResource("/certs/bad_format_cert.crt").getFile(),Charset.defaultCharset().name()); final String certFile = URLDecoder.decode(getClass().getResource("/certs/bad_format_cert.crt").getFile(),Charset.defaultCharset().name());
String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name()); final String keyFile = URLDecoder.decode(getClass().getResource("/certs/rsa_self_signed.key").getFile(),Charset.defaultCharset().name());
String cert = readFileToString(new File(certFile)); final String cert = readFileToString(new File(certFile));
String key = readFileToString(new File(keyFile)); final String key = readFileToString(new File(keyFile));
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO());
//creating the command //creating the command
UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); final UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn();
Class<?> _class = uploadCmd.getClass().getSuperclass(); final Class<?> klazz = uploadCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("cert"); final Field certField = klazz.getDeclaredField("cert");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(uploadCmd, cert); certField.set(uploadCmd, cert);
Field keyField = _class.getDeclaredField("key"); final Field keyField = klazz.getDeclaredField("key");
keyField.setAccessible(true); keyField.setAccessible(true);
keyField.set(uploadCmd, key); keyField.set(uploadCmd, key);
try { certService.uploadSslCert(uploadCmd);
certService.uploadSslCert(uploadCmd); fail("Given a Certificate in bad format (Not PEM), upload should fail");
fail("Given a Certificate in bad format (Not PEM), upload should fail");
} catch (Exception e) {
assertTrue(e.getMessage().contains("Invalid certificate format"));
}
} }
@Test @Test
@ -617,18 +617,18 @@ public class CertServiceTest {
*/ */
public void runDeleteSslCertValid() throws Exception { public void runDeleteSslCertValid() throws Exception {
TransactionLegacy txn = TransactionLegacy.open("runDeleteSslCertValid"); TransactionLegacy.open("runDeleteSslCertValid");
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
long certId = 1; final long certId = 1;
//setting mock objects //setting mock objects
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
@ -641,10 +641,10 @@ public class CertServiceTest {
when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null); when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null);
//creating the command //creating the command
DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); final DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn();
Class<?> _class = deleteCmd.getClass().getSuperclass(); final Class<?> klazz = deleteCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("id"); final Field certField = klazz.getDeclaredField("id");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(deleteCmd, certId); certField.set(deleteCmd, certId);
@ -654,19 +654,19 @@ public class CertServiceTest {
@Test @Test
public void runDeleteSslCertBoundCert() throws NoSuchFieldException, IllegalAccessException { public void runDeleteSslCertBoundCert() throws NoSuchFieldException, IllegalAccessException {
TransactionLegacy txn = TransactionLegacy.open("runDeleteSslCertBoundCert"); TransactionLegacy.open("runDeleteSslCertBoundCert");
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
//setting mock objects //setting mock objects
long certId = 1; final long certId = 1;
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
@ -676,7 +676,7 @@ public class CertServiceTest {
// rule holding the cert // rule holding the cert
certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class);
List<LoadBalancerCertMapVO> lbMapList = new ArrayList<LoadBalancerCertMapVO>(); final List<LoadBalancerCertMapVO> lbMapList = new ArrayList<LoadBalancerCertMapVO>();
lbMapList.add(new LoadBalancerCertMapVO()); lbMapList.add(new LoadBalancerCertMapVO());
certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class);
@ -686,17 +686,17 @@ public class CertServiceTest {
when(certService._entityMgr.findById(eq(LoadBalancerVO.class), anyLong())).thenReturn(new LoadBalancerVO()); when(certService._entityMgr.findById(eq(LoadBalancerVO.class), anyLong())).thenReturn(new LoadBalancerVO());
//creating the command //creating the command
DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); final DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn();
Class<?> _class = deleteCmd.getClass().getSuperclass(); final Class<?> klazz = deleteCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("id"); final Field certField = klazz.getDeclaredField("id");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(deleteCmd, certId); certField.set(deleteCmd, certId);
try { try {
certService.deleteSslCert(deleteCmd); certService.deleteSslCert(deleteCmd);
fail("Delete with a cert id bound to a lb should fail"); fail("Delete with a cert id bound to a lb should fail");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Certificate in use by a loadbalancer")); assertTrue(e.getMessage().contains("Certificate in use by a loadbalancer"));
} }
@ -704,17 +704,17 @@ public class CertServiceTest {
@Test @Test
public void runDeleteSslCertInvalidId() throws NoSuchFieldException, IllegalAccessException { public void runDeleteSslCertInvalidId() throws NoSuchFieldException, IllegalAccessException {
TransactionLegacy txn = TransactionLegacy.open("runDeleteSslCertInvalidId"); TransactionLegacy.open("runDeleteSslCertInvalidId");
long certId = 1; final long certId = 1;
CertServiceImpl certService = new CertServiceImpl(); final CertServiceImpl certService = new CertServiceImpl();
certService._accountMgr = Mockito.mock(AccountManager.class); certService._accountMgr = Mockito.mock(AccountManager.class);
Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString()); final Account account = new AccountVO("testaccount", 1, "networkdomain", (short)0, UUID.randomUUID().toString());
when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); when(certService._accountMgr.getAccount(anyLong())).thenReturn(account);
certService._domainDao = Mockito.mock(DomainDao.class); certService._domainDao = Mockito.mock(DomainDao.class);
DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain"); final DomainVO domain = new DomainVO("networkdomain", 1L, 1L, "networkdomain");
when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain); when(certService._domainDao.findByIdIncludingRemoved(anyLong())).thenReturn(domain);
certService._sslCertDao = Mockito.mock(SslCertDao.class); certService._sslCertDao = Mockito.mock(SslCertDao.class);
@ -726,17 +726,17 @@ public class CertServiceTest {
when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null); when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null);
//creating the command //creating the command
DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); final DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn();
Class<?> _class = deleteCmd.getClass().getSuperclass(); final Class<?> klazz = deleteCmd.getClass().getSuperclass();
Field certField = _class.getDeclaredField("id"); final Field certField = klazz.getDeclaredField("id");
certField.setAccessible(true); certField.setAccessible(true);
certField.set(deleteCmd, certId); certField.set(deleteCmd, certId);
try { try {
certService.deleteSslCert(deleteCmd); certService.deleteSslCert(deleteCmd);
fail("Delete with an invalid ID should fail"); fail("Delete with an invalid ID should fail");
} catch (Exception e) { } catch (final Exception e) {
assertTrue(e.getMessage().contains("Invalid certificate id")); assertTrue(e.getMessage().contains("Invalid certificate id"));
} }

View File

@ -76,8 +76,8 @@
<!-- Another implementation of SSL protocol. Does not work with broken MS RDP SSL too. --> <!-- Another implementation of SSL protocol. Does not work with broken MS RDP SSL too. -->
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId> <artifactId>bcprov-jdk15on</artifactId>
<version>1.46</version> <version>${cs.bcprov.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -16,23 +16,24 @@
// under the License. // under the License.
package streamer.bco; package streamer.bco;
import org.apache.log4j.Logger;
import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.ServerOnlyTlsAuthentication;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import streamer.Direction;
import streamer.Event;
import streamer.SocketWrapperImpl;
import streamer.ssl.SSLState;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.x509.X509CertificateStructure;
import org.bouncycastle.crypto.tls.CertificateVerifyer;
import org.bouncycastle.crypto.tls.TlsProtocolHandler;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import streamer.Direction;
import streamer.Event;
import streamer.SocketWrapperImpl;
import streamer.ssl.SSLState;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class BcoSocketWrapperImpl extends SocketWrapperImpl { public class BcoSocketWrapperImpl extends SocketWrapperImpl {
private static final Logger s_logger = Logger.getLogger(BcoSocketWrapperImpl.class); private static final Logger s_logger = Logger.getLogger(BcoSocketWrapperImpl.class);
@ -41,7 +42,7 @@ public class BcoSocketWrapperImpl extends SocketWrapperImpl {
Security.addProvider(new BouncyCastleProvider()); Security.addProvider(new BouncyCastleProvider());
} }
private TlsProtocolHandler bcoSslSocket; private TlsClientProtocol bcoSslSocket;
public BcoSocketWrapperImpl(String id, SSLState sslState) { public BcoSocketWrapperImpl(String id, SSLState sslState) {
super(id, sslState); super(id, sslState);
@ -60,25 +61,25 @@ public class BcoSocketWrapperImpl extends SocketWrapperImpl {
try { try {
SecureRandom secureRandom = new SecureRandom(); SecureRandom secureRandom = new SecureRandom();
bcoSslSocket = new TlsProtocolHandler(socket.getInputStream(), socket.getOutputStream(), secureRandom); bcoSslSocket = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), secureRandom);
CertificateVerifyer client = new CertificateVerifyer() {
bcoSslSocket.connect(new DefaultTlsClient() {
@Override @Override
public boolean isValid(X509CertificateStructure[] chain) { public TlsAuthentication getAuthentication() throws IOException {
return new ServerOnlyTlsAuthentication() {
try { @Override
if (sslState != null) { public void notifyServerCertificate(final Certificate certificate) throws IOException {
sslState.serverCertificateSubjectPublicKeyInfo = chain[0].getSubjectPublicKeyInfo().getEncoded(); try {
if (sslState != null) {
sslState.serverCertificateSubjectPublicKeyInfo = certificate.getCertificateAt(0).getSubjectPublicKeyInfo().getEncoded();
}
} catch (IOException e) {
throw new RuntimeException("Cannot get server public key.", e);
}
} }
} catch (IOException e) { };
throw new RuntimeException("Cannot get server public key.", e);
}
return true;
} }
}; });
bcoSslSocket.connect(client);
InputStream sis = bcoSslSocket.getInputStream(); InputStream sis = bcoSslSocket.getInputStream();
source.setInputStream(sis); source.setInputStream(sis);

View File

@ -20,7 +20,7 @@
# #
export MAVEN_OPTS="-Xmx4096m -XX:MaxPermSize=800m -Djava.security.egd=file:/dev/urandom" export MAVEN_OPTS="-Xmx4096m -XX:MaxPermSize=800m -Djava.security.egd=file:/dev/urandom"
echo -e "\nStarting simulator" echo -e "\nStarting simulator"
mvn -Dsimulator -pl :cloud-client-ui jetty:run 2>&1 > /tmp/jetty-log & mvn -Dsimulator -Dorg.eclipse.jetty.annotations.maxWait=120 -pl :cloud-client-ui jetty:run 2>&1 > /tmp/jetty-log &
while ! nc -vzw 5 localhost 8096 2>&1 > /dev/null; do grep Exception /tmp/jetty-log; sleep 10; done while ! nc -vzw 5 localhost 8096 2>&1 > /dev/null; do grep Exception /tmp/jetty-log; sleep 10; done
echo -e "\nStarting DataCenter deployment" echo -e "\nStarting DataCenter deployment"

View File

@ -106,7 +106,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Test dependency in mysql for db tests --> <!-- Test dependency in mysql for db tests -->

View File

@ -19,7 +19,10 @@
package com.cloud.utils; package com.cloud.utils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -40,6 +43,13 @@ public class PasswordGenerator {
static private int minLength = 3; static private int minLength = 3;
static {
BouncyCastleProvider provider = new BouncyCastleProvider();
if (Security.getProvider(provider.getName()) == null) {
Security.addProvider(provider);
}
}
public static String generateRandomPassword(int num) { public static String generateRandomPassword(int num) {
Random r = new SecureRandom(); Random r = new SecureRandom();
StringBuilder password = new StringBuilder(); StringBuilder password = new StringBuilder();

View File

@ -19,6 +19,13 @@
package com.cloud.utils.security; package com.cloud.utils.security;
import com.cloud.utils.Ternary;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -40,124 +47,143 @@ import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.codec.binary.Base64;
import com.cloud.utils.Ternary;
import org.bouncycastle.openssl.PEMReader;
public class CertificateHelper { public class CertificateHelper {
public static byte[] buildAndSaveKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException, public static byte[] buildAndSaveKeystore(final String alias, final String cert, final String privateKey, final String storePassword) throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, InvalidKeySpecException, IOException { NoSuchAlgorithmException, InvalidKeySpecException, IOException {
KeyStore ks = buildKeystore(alias, cert, privateKey, storePassword); Preconditions.checkArgument(!Strings.isNullOrEmpty(alias), "Certificate alias cannot be blank");
Preconditions.checkArgument(!Strings.isNullOrEmpty(cert), "Certificate cannot be blank");
Preconditions.checkArgument(!Strings.isNullOrEmpty(privateKey), "Private key cannot be blank");
ByteArrayOutputStream os = new ByteArrayOutputStream(); final KeyStore ks = buildKeystore(alias, cert, privateKey, storePassword);
ks.store(os, storePassword != null ? storePassword.toCharArray() : null);
os.close(); try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) {
return os.toByteArray(); ks.store(os, storePassword != null ? storePassword.toCharArray() : null);
return os.toByteArray();
}
} }
public static byte[] buildAndSaveKeystore(List<Ternary<String, String, String>> certs, String storePassword) throws KeyStoreException, NoSuchAlgorithmException, public static byte[] buildAndSaveKeystore(final List<Ternary<String, String, String>> certs, final String storePassword) throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException, InvalidKeySpecException { CertificateException, IOException, InvalidKeySpecException {
KeyStore ks = KeyStore.getInstance("JKS"); Preconditions.checkNotNull(certs, "List of certificates to be saved in keystore cannot be null");
ks.load(null, storePassword != null ? storePassword.toCharArray() : null); char password[] = null;
if (storePassword != null) {
password = storePassword.toCharArray();
}
final KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, password);
//name,cert,key //name,cert,key
for (Ternary<String, String, String> cert : certs) { for (final Ternary<String, String, String> cert : certs) {
if (cert.third() == null) { if (cert.third() == null) {
Certificate c = buildCertificate(cert.second()); final Certificate c = buildCertificate(cert.second());
ks.setCertificateEntry(cert.first(), c); ks.setCertificateEntry(cert.first(), c);
} else { } else {
Certificate[] c = new Certificate[certs.size()]; final Certificate[] c = new Certificate[certs.size()];
int i = certs.size(); int i = certs.size();
for (Ternary<String, String, String> ct : certs) { for (final Ternary<String, String, String> ct : certs) {
c[i - 1] = buildCertificate(ct.second()); c[i - 1] = buildCertificate(ct.second());
i--; i--;
} }
ks.setKeyEntry(cert.first(), buildPrivateKey(cert.third()), storePassword != null ? storePassword.toCharArray() : null, c); ks.setKeyEntry(cert.first(), buildPrivateKey(cert.third()), password, c);
} }
} }
ByteArrayOutputStream os = new ByteArrayOutputStream(); try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) {
ks.store(os, storePassword != null ? storePassword.toCharArray() : null); ks.store(os, password);
os.close(); return os.toByteArray();
return os.toByteArray(); }
} }
public static KeyStore loadKeystore(byte[] ksData, String storePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { public static KeyStore loadKeystore(final byte[] ksData, final String storePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
assert (ksData != null); Preconditions.checkNotNull(ksData, "Keystore data cannot be null");
KeyStore ks = KeyStore.getInstance("JKS"); final KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new ByteArrayInputStream(ksData), storePassword != null ? storePassword.toCharArray() : null); try (final ByteArrayInputStream is = new ByteArrayInputStream(ksData)) {
ks.load(is, storePassword != null ? storePassword.toCharArray() : null);
}
return ks; return ks;
} }
public static KeyStore buildKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException, public static KeyStore buildKeystore(final String alias, final String cert, final String privateKey, final String storePassword) throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, InvalidKeySpecException, IOException { NoSuchAlgorithmException, InvalidKeySpecException, IOException {
Preconditions.checkArgument(!Strings.isNullOrEmpty(alias), "Certificate alias cannot be blank");
Preconditions.checkArgument(!Strings.isNullOrEmpty(cert), "Certificate cannot be blank");
Preconditions.checkArgument(!Strings.isNullOrEmpty(privateKey), "Private key cannot be blank");
KeyStore ks = KeyStore.getInstance("JKS"); char password[] = null;
ks.load(null, storePassword != null ? storePassword.toCharArray() : null); if (storePassword != null) {
Certificate[] certs = new Certificate[1]; password = storePassword.toCharArray();
}
final KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, password);
final Certificate[] certs = new Certificate[1];
certs[0] = buildCertificate(cert); certs[0] = buildCertificate(cert);
ks.setKeyEntry(alias, buildPrivateKey(privateKey), storePassword != null ? storePassword.toCharArray() : null, certs); ks.setKeyEntry(alias, buildPrivateKey(privateKey), password, certs);
return ks; return ks;
} }
public static Certificate buildCertificate(String content) throws CertificateException { public static Certificate buildCertificate(final String content) throws CertificateException {
assert (content != null); Preconditions.checkNotNull(content, "Certificate content cannot be null");
BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(content.getBytes())); final BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(content.getBytes()));
CertificateFactory cf = CertificateFactory.getInstance("X.509"); final CertificateFactory cf = CertificateFactory.getInstance("X.509");
return cf.generateCertificate(bis); return cf.generateCertificate(bis);
} }
public static Key buildPrivateKey(String base64EncodedKeyContent) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { public static Key buildPrivateKey(final String base64EncodedKeyContent) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
KeyFactory kf = KeyFactory.getInstance("RSA"); Preconditions.checkNotNull(base64EncodedKeyContent);
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64EncodedKeyContent));
final KeyFactory kf = KeyFactory.getInstance("RSA");
final PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64EncodedKeyContent));
return kf.generatePrivate(keysp); return kf.generatePrivate(keysp);
} }
public static List<Certificate> parseChain(String chain) throws IOException { public static List<Certificate> parseChain(final String chain) throws IOException, CertificateException {
Preconditions.checkNotNull(chain);
List<Certificate> certs = new ArrayList<Certificate>(); final List<Certificate> certs = new ArrayList<Certificate>();
PEMReader reader = new PEMReader(new StringReader(chain)); try(final PemReader pemReader = new PemReader(new StringReader(chain));)
{
final PemObject pemObject = pemReader.readPemObject();
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
final ByteArrayInputStream bais = new ByteArrayInputStream(pemObject.getContent());
Certificate crt = null; for (final Certificate cert : certificateFactory.generateCertificates(bais)) {
if (cert instanceof X509Certificate) {
while ((crt = (Certificate)reader.readObject()) != null) { certs.add(cert);
if (crt instanceof X509Certificate) { }
certs.add(crt); }
if (certs.isEmpty()) {
throw new IllegalStateException("Unable to decode certificate chain");
} }
} }
if (certs.size() == 0)
throw new IllegalArgumentException("Unable to decode certificate chain");
return certs; return certs;
} }
public static String generateFingerPrint(Certificate cert) { public static String generateFingerPrint(final Certificate cert) {
Preconditions.checkNotNull(cert, "Certificate cannot be null");
final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
StringBuilder buffer = new StringBuilder(60); final StringBuilder buffer = new StringBuilder(60);
try { try {
MessageDigest md = MessageDigest.getInstance("SHA-1"); final MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] data = md.digest(cert.getEncoded()); final byte[] data = md.digest(cert.getEncoded());
for (int i = 0; i < data.length; i++) { for (final byte element : data) {
if (buffer.length() > 0) { if (buffer.length() > 0) {
buffer.append(":"); buffer.append(":");
} }
buffer.append(HEX[(0xF0 & data[i]) >>> 4]); buffer.append(HEX[(0xF0 & element) >>> 4]);
buffer.append(HEX[0x0F & data[i]]); buffer.append(HEX[0x0F & element]);
} }
} catch (CertificateEncodingException e) { } catch (final CertificateEncodingException e) {
throw new CloudRuntimeException("Bad certificate encoding"); throw new IllegalStateException("Bad certificate encoding");
} catch (NoSuchAlgorithmException e) { } catch (final NoSuchAlgorithmException e) {
throw new CloudRuntimeException("Bad certificate algorithm"); throw new IllegalStateException("Bad certificate algorithm");
} }
return buffer.toString(); return buffer.toString();