diff --git a/CHANGES b/CHANGES index 054e7b06615..e3e316e9dc9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,4 @@ + Apache CloudStack CHANGES ====================================== diff --git a/api/src/com/cloud/agent/api/to/LoadBalancerTO.java b/api/src/com/cloud/agent/api/to/LoadBalancerTO.java index df2f8a87490..4caa1b2f85c 100644 --- a/api/src/com/cloud/agent/api/to/LoadBalancerTO.java +++ b/api/src/com/cloud/agent/api/to/LoadBalancerTO.java @@ -33,6 +33,7 @@ import com.cloud.network.lb.LoadBalancingRule.LbCondition; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; import com.cloud.utils.Pair; @@ -41,6 +42,7 @@ public class LoadBalancerTO { String srcIp; int srcPort; String protocol; + String lbProtocol; String algorithm; boolean revoked; boolean alreadyAdded; @@ -48,6 +50,7 @@ public class LoadBalancerTO { DestinationTO[] destinations; private StickinessPolicyTO[] stickinessPolicies; private HealthCheckPolicyTO[] healthCheckPolicies; + private LbSslCert sslCert; /* XXX: Should this be SslCertTO? */ private AutoScaleVmGroupTO autoScaleVmGroupTO; final static int MAX_STICKINESS_POLICIES = 1; final static int MAX_HEALTHCHECK_POLICIES = 1; @@ -66,6 +69,8 @@ public class LoadBalancerTO { this.inline = inline; this.destinations = new DestinationTO[destinations.size()]; this.stickinessPolicies = null; + this.sslCert = null; + this.lbProtocol = null; int i = 0; for (LbDestination destination : destinations) { this.destinations[i++] = new DestinationTO(destination.getIpAddress(), destination.getDestinationPortStart(), destination.isRevoked(), false); @@ -77,12 +82,12 @@ public class LoadBalancerTO { List stickinessPolicies) { this(id, srcIp, srcPort, protocol, algorithm, revoked, alreadyAdded, inline, arg_destinations, - stickinessPolicies, null); + stickinessPolicies, null, null, null); } public LoadBalancerTO(String id, String srcIp, int srcPort, String protocol, String algorithm, boolean revoked, boolean alreadyAdded, boolean inline, List arg_destinations, - List stickinessPolicies, List healthCheckPolicies) { + List stickinessPolicies, List healthCheckPolicies, LbSslCert sslCert, String lbProtocol) { this(id, srcIp, srcPort, protocol, algorithm, revoked, alreadyAdded, inline, arg_destinations); this.stickinessPolicies = null; this.healthCheckPolicies = null; @@ -117,6 +122,9 @@ public class LoadBalancerTO { if (index == 0) this.healthCheckPolicies = null; } + + this.sslCert = sslCert; + this.lbProtocol = lbProtocol; } protected LoadBalancerTO() { @@ -142,6 +150,10 @@ public class LoadBalancerTO { return protocol; } + public String getLbProtocol() { + return lbProtocol; + } + public boolean isRevoked() { return revoked; } @@ -178,6 +190,10 @@ public class LoadBalancerTO { return this.autoScaleVmGroupTO != null; } + public LbSslCert getSslCert(){ + return this.sslCert; + } + public static class StickinessPolicyTO { private String _methodName; private List> _paramsList; @@ -294,6 +310,8 @@ public class LoadBalancerTO { public String getMonitorState() { return monitorState; } + + } public static class CounterTO implements Serializable { private final String name; @@ -558,5 +576,4 @@ public class LoadBalancerTO { autoScaleVmGroupTO = new AutoScaleVmGroupTO(autoScaleVmGroup.getUuid(), autoScaleVmGroup.getMinMembers(), autoScaleVmGroup.getMaxMembers(), autoScaleVmGroup.getMemberPort(), autoScaleVmGroup.getInterval(), autoScalePolicyTOs, autoScaleVmProfileTO, autoScaleVmGroup.getState(), lbAutoScaleVmGroup.getCurrentState()); } - } diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index d9f80eb2a2c..a3e45fadce2 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -133,6 +133,10 @@ public class EventTypes { public static final String EVENT_LB_HEALTHCHECKPOLICY_CREATE = "LB.HEALTHCHECKPOLICY.CREATE"; public static final String EVENT_LB_HEALTHCHECKPOLICY_DELETE = "LB.HEALTHCHECKPOLICY.DELETE"; public static final String EVENT_LOAD_BALANCER_UPDATE = "LB.UPDATE"; + public static final String EVENT_LB_CERT_UPLOAD = "LB.CERT.UPLOAD"; + public static final String EVENT_LB_CERT_DELETE = "LB.CERT.DELETE"; + public static final String EVENT_LB_CERT_ASSIGN = "LB.CERT.ASSIGN"; + public static final String EVENT_LB_CERT_REMOVE = "LB.CERT.REMOVE"; // Global Load Balancer rules public static final String EVENT_ASSIGN_TO_GLOBAL_LOAD_BALANCER_RULE = "GLOBAL.LB.ASSIGN"; @@ -511,6 +515,10 @@ public class EventTypes { entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_CREATE, LoadBalancer.class.getName()); entityEventDetails.put(EVENT_LB_STICKINESSPOLICY_DELETE, LoadBalancer.class.getName()); entityEventDetails.put(EVENT_LOAD_BALANCER_UPDATE, LoadBalancer.class.getName()); + entityEventDetails.put(EVENT_LB_CERT_UPLOAD, LoadBalancer.class.getName()); + entityEventDetails.put(EVENT_LB_CERT_DELETE, LoadBalancer.class.getName()); + entityEventDetails.put(EVENT_LB_CERT_ASSIGN, LoadBalancer.class.getName()); + entityEventDetails.put(EVENT_LB_CERT_REMOVE, LoadBalancer.class.getName()); // Account events entityEventDetails.put(EVENT_ACCOUNT_DISABLE, Account.class.getName()); diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 318ac192252..4eadd61aa25 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -181,6 +181,7 @@ public interface Network extends ControlledEntity, StateObject, I public static final Capability SupportedTrafficDirection = new Capability("SupportedTrafficDirection"); public static final Capability SupportedEgressProtocols = new Capability("SupportedEgressProtocols"); public static final Capability HealthCheckPolicy = new Capability("HealthCheckPolicy"); + public static final Capability SslTermination = new Capability("SslTermination"); public static final Capability LbSchemes = new Capability("LbSchemes"); public static final Capability DhcpAccrossMultipleSubnets = new Capability("DhcpAccrossMultipleSubnets"); diff --git a/api/src/com/cloud/network/lb/CertService.java b/api/src/com/cloud/network/lb/CertService.java new file mode 100644 index 00000000000..69d77d6ff4d --- /dev/null +++ b/api/src/com/cloud/network/lb/CertService.java @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.lb; + + +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 java.util.List; + +public interface CertService { + + public SslCertResponse uploadSslCert(UploadSslCertCmd certCmd); + public void deleteSslCert(DeleteSslCertCmd deleteSslCertCmd); + public List listSslCerts(ListSslCertsCmd listSslCertCmd); +} \ No newline at end of file diff --git a/api/src/com/cloud/network/lb/LoadBalancingRule.java b/api/src/com/cloud/network/lb/LoadBalancingRule.java index 4b37782a8c7..39c969c7001 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRule.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRule.java @@ -36,9 +36,11 @@ public class LoadBalancingRule { private List stickinessPolicies; private LbAutoScaleVmGroup autoScaleVmGroup; private List healthCheckPolicies; + private LbSslCert sslCert; + private String lbProtocol; public LoadBalancingRule(LoadBalancer lb, List destinations, - List stickinessPolicies, List healthCheckPolicies, Ip sourceIp) { + List stickinessPolicies, List healthCheckPolicies, Ip sourceIp) { this.lb = lb; this.destinations = destinations; this.stickinessPolicies = stickinessPolicies; @@ -46,6 +48,17 @@ public class LoadBalancingRule { this.sourceIp = sourceIp; } + public LoadBalancingRule(LoadBalancer lb, List destinations, + List stickinessPolicies, List healthCheckPolicies, Ip sourceIp, LbSslCert sslCert, String lbProtocol) { + this.lb = lb; + this.destinations = destinations; + this.stickinessPolicies = stickinessPolicies; + this.healthCheckPolicies = healthCheckPolicies; + this.sourceIp = sourceIp; + this.sslCert = sslCert; + this.lbProtocol = lbProtocol; + } + public long getId() { return lb.getId(); } @@ -90,6 +103,10 @@ public class LoadBalancingRule { return lb.getProtocol(); } + public String getLbProtocol() { + return this.lbProtocol; + } + public FirewallRule.Purpose getPurpose() { return FirewallRule.Purpose.LoadBalancing; } @@ -123,6 +140,10 @@ public class LoadBalancingRule { return healthCheckPolicies; } + public LbSslCert getLbSslCert(){ + return sslCert; + } + public interface Destination { String getIpAddress(); @@ -415,6 +436,44 @@ public class LoadBalancingRule { } } + public static class LbSslCert { + private String cert; + private String key; + private String password=null; + private String chain=null; + private boolean revoked; + + + public LbSslCert(String cert, String key, String password, String chain, boolean revoked) { + this.cert = cert; + this.key = key; + this.password = password; + this.chain = chain; + this.revoked = revoked; + } + + public String getCert() { + + return cert; + } + + public String getKey() { + return key; + } + + public String getPassword() { + return password; + } + + public String getChain() { + return chain; + } + + public boolean isRevoked(){ + return revoked; + } + } + public Ip getSourceIp() { return sourceIp; } diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java index 59d5c8dec05..298426b27b4 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java @@ -52,7 +52,7 @@ public interface LoadBalancingRulesService { */ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String description, int srcPortStart, int srcPortEnd, int defPortStart, int defPortEnd, Long ipAddrId, String protocol, String algorithm, - long networkId, long lbOwnerId, boolean openFirewall) throws NetworkRuleConflictException, InsufficientAddressCapacityException; + long networkId, long lbOwnerId, boolean openFirewall, String lbProtocol) throws NetworkRuleConflictException, InsufficientAddressCapacityException; LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd); @@ -94,10 +94,16 @@ public interface LoadBalancingRulesService { */ boolean assignToLoadBalancer(long lbRuleId, List vmIds); + boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey); + boolean removeFromLoadBalancer(long lbRuleId, List vmIds); boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException; + boolean assignCertToLoadBalancer(long lbRuleId, Long CertId); + boolean removeCertFromLoadBalancer(long lbRuleId); + + /** * List instances that have either been applied to a load balancer or are eligible to be assigned to a load * balancer. diff --git a/api/src/com/cloud/network/lb/SslCert.java b/api/src/com/cloud/network/lb/SslCert.java new file mode 100644 index 00000000000..f7a7c4b790e --- /dev/null +++ b/api/src/com/cloud/network/lb/SslCert.java @@ -0,0 +1,16 @@ +package com.cloud.network.lb; + + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface SslCert extends InternalIdentity, Identity, ControlledEntity { + + public String getCertificate(); + public String getKey() ; + public String getChain(); + public String getPassword(); + public String getFingerPrint(); + +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index a348684f18f..ae6be63dcf9 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -36,6 +36,9 @@ public class ApiConstants { public static final String CATEGORY = "category"; public static final String CAN_REVERT = "canrevert"; public static final String CERTIFICATE = "certificate"; + public static final String CERTIFICATE_CHAIN = "certchain"; + public static final String CERTIFICATE_FINGERPRINT = "fingerprint"; + public static final String CERTIFICATE_ID = "certid"; public static final String PRIVATE_KEY = "privatekey"; public static final String DOMAIN_SUFFIX = "domainsuffix"; public static final String DNS_SEARCH_ORDER = "dnssearchorder"; diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java new file mode 100644 index 00000000000..253c015469e --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.loadbalancer; + +import com.cloud.event.EventTypes; +import com.cloud.exception.*; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.user.Account; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.SslCertResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +@APICommand(name = "assignCertToLoadBalancer", description = "Assigns a certificate to a Load Balancer Rule", responseObject = SuccessResponse.class) +public class AssignCertToLoadBalancerCmd extends BaseAsyncCmd { + + public static final Logger s_logger = Logger + .getLogger(AssignCertToLoadBalancerCmd.class.getName()); + + private static final String s_name = "assignCertToLoadBalancer"; + + + @Parameter(name = ApiConstants.LBID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, + required = true, description = "the ID of the load balancer rule") + Long lbRuleId; + + @Parameter(name = ApiConstants.CERTIFICATE_ID, type = CommandType.UUID, entityType = SslCertResponse.class, + required = true, description = "the ID of the certificate") + Long certId; + + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + //To change body of implemented methods use File | Settings | File Templates. + if ( _lbService.assignCertToLoadBalancer( getLbRuleId(), getCertId()) ) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to assign certificate to loadbalancer"); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LB_CERT_ASSIGN; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public String getEventDescription() { + return "Assigining a certificate to a loadbalancer"; + } + + + @Override + public long getEntityOwnerId() { + LoadBalancer lb = _entityMgr.findById(LoadBalancer.class, getLbRuleId()); + if (lb == null) { + return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked + } + return lb.getAccountId(); + } + + + + public Long getCertId(){ + return certId; + } + + public Long getLbRuleId(){ + return lbRuleId; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java index a36843634cc..e4cc0e613db 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java @@ -102,6 +102,9 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements "rule will be created for. Required when public Ip address is not associated with any Guest network yet (VPC case)") private Long networkId; + @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, description="The protocol for the LB") + private String lbProtocol; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -227,6 +230,10 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements return null; } + public String getLbProtocol(){ + return lbProtocol; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -282,7 +289,7 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements try { LoadBalancer result = _lbService.createPublicLoadBalancerRule(getXid(), getName(), getDescription(), getSourcePortStart(), getSourcePortEnd(), getDefaultPortStart(), getDefaultPortEnd(), getSourceIpAddressId(), getProtocol(), getAlgorithm(), - getNetworkId(), getEntityOwnerId(), getOpenFirewall()); + getNetworkId(), getEntityOwnerId(), getOpenFirewall(), getLbProtocol()); this.setEntityId(result.getId()); this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java new file mode 100644 index 00000000000..19e36d2b7b6 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.loadbalancer; + + +import com.cloud.network.lb.CertService; +import org.apache.cloudstack.api.response.SslCertResponse; +import com.cloud.exception.*; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +@APICommand(name = "deleteSslCert", description="Delete a certificate to cloudstack", responseObject=SuccessResponse.class) +public class DeleteSslCertCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(DeleteSslCertCmd.class.getName()); + + private static final String s_name = "deletesslcertresponse"; + + @Inject + CertService _certService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name= ApiConstants.ID, type=CommandType.UUID, entityType = SslCertResponse.class, required=true, description="Id of SSL certificate") + private Long id; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + _certService.deleteSslCert(this); + SuccessResponse rsp = new SuccessResponse(); + rsp.setResponseName(getCommandName()); + rsp.setObjectName("success"); + this.setResponseObject(rsp); + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + +} \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListSslCertsCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListSslCertsCmd.java new file mode 100644 index 00000000000..3df28a39b80 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListSslCertsCmd.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.loadbalancer; + + +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.SslCertResponse; +import com.cloud.network.lb.CertService; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = "listSslCerts", description="Lists SSL certificates", responseObject=SslCertResponse.class) +public class ListSslCertsCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(DeleteSslCertCmd.class.getName()); + + private static final String s_name = "listsslcertsresponse"; + + @Inject + CertService _certService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name= ApiConstants.CERTIFICATE_ID, type=CommandType.UUID, entityType = SslCertResponse.class, required=false, description="Id of SSL certificate") + private Long certId; + + @Parameter(name= ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class, required=false, description="Account Id") + private Long accountId; + + @Parameter(name= ApiConstants.LBID, type=CommandType.UUID, entityType = FirewallRuleResponse.class, required=false, description="Loadbalancer Rule Id") + private Long lbId; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getCertId() { + return certId; + } + + public Long getAccountId() { + return accountId; + } + + public Long getLbId(){ + return lbId; + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute(){ + + + try { + List certResponseList = _certService.listSslCerts(this); + ListResponse response = new ListResponse(); + + response.setResponses(certResponseList); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + + } catch (Exception e) { + throw new CloudRuntimeException(e); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } +} \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/RemoveCertFromLoadBalancerCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/RemoveCertFromLoadBalancerCmd.java new file mode 100644 index 00000000000..059d16320f6 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/RemoveCertFromLoadBalancerCmd.java @@ -0,0 +1,82 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.loadbalancer; + + +import com.cloud.event.EventTypes; +import com.cloud.exception.*; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.user.Account; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + + +@APICommand(name = "removeCertFromLoadBalancer", description = "Removes a certificate from a Load Balancer Rule", responseObject = SuccessResponse.class) +public class RemoveCertFromLoadBalancerCmd extends BaseAsyncCmd{ + + public static final Logger s_logger = Logger.getLogger(RemoveCertFromLoadBalancerCmd.class.getName()); + + private static final String s_name = "removeCertFromLoadBalancer"; + + + @Parameter(name = ApiConstants.LBID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, + required = true, description = "the ID of the load balancer rule") + Long lbRuleId; + + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + boolean result = _lbService.removeCertFromLoadBalancer(getLbRuleId()); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove certificate from load balancer rule"); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LB_CERT_REMOVE; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public String getEventDescription() { + return "Removing a certificate from a loadbalancer with ID " + getLbRuleId(); + } + + + @Override + public long getEntityOwnerId() { + LoadBalancer lb = _entityMgr.findById(LoadBalancer.class, getLbRuleId()); + if (lb == null) { + return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked + } + return lb.getAccountId(); + } + + public Long getLbRuleId(){ + return this.lbRuleId; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java new file mode 100644 index 00000000000..897d66b73c1 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/UploadSslCertCmd.java @@ -0,0 +1,103 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.loadbalancer; + + +import org.apache.cloudstack.api.response.SslCertResponse; +import com.cloud.exception.*; +import com.cloud.network.lb.CertService; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +@APICommand(name = "uploadSslCert", description="Upload a certificate to cloudstack", responseObject=SslCertResponse.class) +public class UploadSslCertCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(UploadSslCertCmd.class.getName()); + + private static final String s_name = "uploadsslcertresponse"; + + @Inject CertService _certService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name= ApiConstants.CERTIFICATE, type=CommandType.STRING, required=true, description="SSL certificate",length=16384) + private String cert; + + @Parameter(name=ApiConstants.PRIVATE_KEY, type=CommandType.STRING, required=true, description="Private key", length=16384) + private String key; + + @Parameter(name=ApiConstants.CERTIFICATE_CHAIN, type=CommandType.STRING, description="Certificate chain of trust", length=2097152) + private String chain; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="Password for the private key") + private String password; + + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getCert() { + return cert; + } + + public String getKey() { + return key; + } + + public String getChain() { + return chain; + } + + public String getPassword() { + return password; + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + + try{ + SslCertResponse response = _certService.uploadSslCert(this); + setResponseObject(response); + response.setResponseName(getCommandName()); + } catch (Exception e){ + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + +} \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/response/SslCertResponse.java b/api/src/org/apache/cloudstack/api/response/SslCertResponse.java new file mode 100644 index 00000000000..3e8b7ae559d --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/SslCertResponse.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import com.cloud.network.lb.SslCert; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import java.util.List; +//import org.apache.cloudstack.api.EntityReference; + +@EntityReference(value= SslCert.class) +public class SslCertResponse extends BaseResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "SSL certificate ID") + private String id; + + @SerializedName(ApiConstants.CERTIFICATE) + @Param(description = "certificate") + private String certificate; + + @SerializedName(ApiConstants.PRIVATE_KEY) + @Param(description = "private key") + private String privatekey; + + @SerializedName(ApiConstants.ACCOUNT) + @Param(description = "account for the certificate") + private String accountName; + + @SerializedName(ApiConstants.CERTIFICATE_CHAIN) + @Param(description = "certificate chain") + private String certchain; + + @SerializedName(ApiConstants.CERTIFICATE_FINGERPRINT) + @Param(description = "certificate fingerprint") + private String fingerprint; + + @SerializedName(ApiConstants.LOAD_BALANCER_RULE_LIST) + @Param(description = "List of loabalancers this certificate is bound to") + List lbIds; + + public SslCertResponse() { + } + + public void setId(String id) { + this.id = id; + } + + public void setCertificate(String cert) { + this.certificate = cert; + } + + public void setPrivatekey(String key) { + this.privatekey = key; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public void setCertchain(String chain) { + this.certchain = chain; + } + + public void setFingerprint(String fingerprint){ + this.fingerprint = fingerprint; + } + + public void setLbIds(List lbIds){ + this.lbIds = lbIds; + } +} diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 68d7303d0a7..cb9dcf0b071 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -165,6 +165,14 @@ deleteLBHealthCheckPolicy=15 listLoadBalancerRuleInstances=15 updateLoadBalancerRule=15 +##### SSL offload commands + +uploadSslCert=15 +deleteSslCert=15 +listSslCerts=15 +assignCertToLoadBalancer=15 +removeCertFromLoadBalancer=15 + #### autoscale commands createCounter=1 createCondition=15 diff --git a/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java b/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java index 3a51e8ad6be..a6a46d55665 100644 --- a/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java +++ b/core/src/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java @@ -33,6 +33,7 @@ public class LoadBalancerConfigCommand extends NetworkElementCommand { public String lbStatsAuth = "admin1:AdMiN123"; public String lbStatsUri = "/admin?stats"; public String maxconn =""; + public String lbProtocol; public boolean keepAliveEnabled = false; NicTO nic; Long vpcId; diff --git a/engine/components-api/src/com/cloud/network/lb/LoadBalancingRulesManager.java b/engine/components-api/src/com/cloud/network/lb/LoadBalancingRulesManager.java index 3e325859a9a..22830d5a06a 100644 --- a/engine/components-api/src/com/cloud/network/lb/LoadBalancingRulesManager.java +++ b/engine/components-api/src/com/cloud/network/lb/LoadBalancingRulesManager.java @@ -25,6 +25,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; import com.cloud.network.rules.LbStickinessMethod; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.LoadBalancerContainer.Scheme; @@ -33,7 +34,8 @@ import com.cloud.user.Account; public interface LoadBalancingRulesManager { LoadBalancer createPublicLoadBalancer(String xId, String name, String description, - int srcPort, int destPort, long sourceIpId, String protocol, String algorithm, boolean openFirewall, CallContext caller) + int srcPort, int destPort, long sourceIpId, String protocol, String algorithm, + boolean openFirewall, CallContext caller, String lbProtocol) throws NetworkRuleConflictException; boolean removeAllLoadBalanacersForIp(long ipId, Account caller, long callerUserId); @@ -42,6 +44,7 @@ public interface LoadBalancingRulesManager { List getStickinessPolicies(long lbId); List getStickinessMethods(long networkid); List getHealthCheckPolicies(long lbId); + LbSslCert getLbSslCert(long lbId); /** * Remove vm from all load balancers diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index a64e5c06e7c..c71190b5cf5 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -189,6 +189,7 @@ + @@ -252,6 +253,7 @@ + diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapDao.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapDao.java new file mode 100644 index 00000000000..21c01d9c15e --- /dev/null +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapDao.java @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import com.cloud.network.LBHealthCheckPolicyVO; +import com.cloud.utils.db.GenericDao; + +import java.util.List; + + +public interface LoadBalancerCertMapDao extends GenericDao { + List listByCertId(Long certId); + List listByAccountId(Long accountId); + LoadBalancerCertMapVO findByLbRuleId(Long id); +} diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapDaoImpl.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapDaoImpl.java new file mode 100644 index 00000000000..57506f9a6f0 --- /dev/null +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapDaoImpl.java @@ -0,0 +1,79 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.List; + +@Local(value = {LoadBalancerCertMapDao.class}) +public class LoadBalancerCertMapDaoImpl extends GenericDaoBase implements LoadBalancerCertMapDao { + + private final SearchBuilder listByCertId; + private final SearchBuilder findByLbRuleId; + + + @Inject SslCertDao _sslCertDao; + + public LoadBalancerCertMapDaoImpl() { + + listByCertId = createSearchBuilder(); + listByCertId.and("certificateId", listByCertId.entity().getCertId(), SearchCriteria.Op.EQ); + listByCertId.done(); + + findByLbRuleId = createSearchBuilder(); + findByLbRuleId.and("loadBalancerId", findByLbRuleId.entity().getLbId(), SearchCriteria.Op.EQ); + findByLbRuleId.done(); + + } + + @Override + public List listByCertId(Long certId) { + SearchCriteria sc = listByCertId.create(); + sc.setParameters("certificateId", certId); + return listBy(sc); + } + + @Override + public LoadBalancerCertMapVO findByLbRuleId(Long LbId) { + SearchCriteria sc = findByLbRuleId.create(); + sc.setParameters("loadBalancerId", LbId); + return findOneBy(sc); + } + + @Override + public List listByAccountId(Long accountId) { + + SearchBuilder listByAccountId; + SearchBuilder certsForAccount; + + listByAccountId = createSearchBuilder(); + certsForAccount = _sslCertDao.createSearchBuilder(); + certsForAccount.and("accountId", certsForAccount.entity().getAccountId(), SearchCriteria.Op.EQ); + listByAccountId.join("certsForAccount", certsForAccount, certsForAccount.entity().getId(), listByAccountId.entity().getLbId(), JoinBuilder.JoinType.INNER); + certsForAccount.done(); + listByAccountId.done(); + + SearchCriteria sc = listByAccountId.create(); + sc.setParameters("accountId", accountId); + return listBy(sc); + } +} diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapVO.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapVO.java new file mode 100644 index 00000000000..535964757ec --- /dev/null +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerCertMapVO.java @@ -0,0 +1,96 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + + +import org.apache.cloudstack.api.InternalIdentity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.UUID; + + +@Entity +@Table(name="load_balancer_cert_map") +public class LoadBalancerCertMapVO implements InternalIdentity { + + @Id + @Column(name="id") + private Long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="load_balancer_id") + private Long lbId; + + @Column(name="certificate_id") + private Long certId; + + @Column(name="revoke") + private boolean revoke = false; + + + public LoadBalancerCertMapVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public LoadBalancerCertMapVO(Long lbId, Long certId, boolean revoke) { + + this.lbId = lbId; + this.certId = certId; + this.revoke = revoke; + this.uuid = UUID.randomUUID().toString(); + } + + // Getters + @Override + public long getId() { + return id; + } + + public String getUuid() { + return uuid; + } + + public Long getLbId() { + return lbId; + } + + public Long getCertId() { + return certId; + } + + public boolean isRevoke() { + return revoke; + } + + //Setters + public void setLbId(Long lbId) { + this.lbId = lbId; + } + + public void setCertId(Long certId) { + this.certId = certId; + } + + public void setRevoke(boolean revoke) { + this.revoke = revoke; + } +} diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVO.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVO.java index fee88cf7b0a..625eb6f651a 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVO.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVO.java @@ -59,10 +59,15 @@ public class LoadBalancerVO extends FirewallRuleVO implements LoadBalancer { @Column(name="scheme") Scheme scheme = Scheme.Public; + @Column(name="lb_protocol") + String lbProtocol; + + public LoadBalancerVO() { } - public LoadBalancerVO(String xId, String name, String description, long srcIpId, int srcPort, int dstPort, String algorithm, long networkId, long accountId, long domainId) { + public LoadBalancerVO(String xId, String name, String description, long srcIpId, int srcPort, int dstPort, String algorithm, long networkId, + long accountId, long domainId, String lbProtocol) { super(xId, srcIpId, srcPort, NetUtils.TCP_PROTO, networkId, accountId, domainId, Purpose.LoadBalancing, null, null, null, null); this.name = name; this.description = description; @@ -70,6 +75,7 @@ public class LoadBalancerVO extends FirewallRuleVO implements LoadBalancer { this.defaultPortStart = dstPort; this.defaultPortEnd = dstPort; this.scheme = Scheme.Public; + this.lbProtocol = lbProtocol; } @Override @@ -101,6 +107,14 @@ public class LoadBalancerVO extends FirewallRuleVO implements LoadBalancer { this.name = name; } + public String getLbProtocol(){ + return lbProtocol; + } + + public void setLbProtocol(String lbProtocol){ + this.lbProtocol = lbProtocol; + } + public void setAlgorithm(String algorithm) { this.algorithm = algorithm; } diff --git a/engine/schema/src/com/cloud/network/dao/SslCertDao.java b/engine/schema/src/com/cloud/network/dao/SslCertDao.java new file mode 100644 index 00000000000..37520bbcb90 --- /dev/null +++ b/engine/schema/src/com/cloud/network/dao/SslCertDao.java @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + + +import com.cloud.utils.db.GenericDao; + +import java.util.List; + + +public interface SslCertDao extends GenericDao { + List listByAccountId(Long id); +} \ No newline at end of file diff --git a/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java b/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java new file mode 100644 index 00000000000..483c28d295b --- /dev/null +++ b/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java @@ -0,0 +1,31 @@ +package com.cloud.network.dao; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +import javax.ejb.Local; +import java.util.List; + + + +@Local(value = {SslCertDao.class}) +public class SslCertDaoImpl extends GenericDaoBase implements SslCertDao { + + private final SearchBuilder listByAccountId; + + public SslCertDaoImpl() { + listByAccountId = createSearchBuilder(); + listByAccountId.and("accountId", listByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ); + listByAccountId.done(); + } + + @Override + public List listByAccountId(Long accountId) { + SearchCriteria sc = listByAccountId.create(); + sc.setParameters("accountId", accountId); + return listBy(sc); + } + + +} diff --git a/engine/schema/src/com/cloud/network/dao/SslCertVO.java b/engine/schema/src/com/cloud/network/dao/SslCertVO.java new file mode 100644 index 00000000000..c26c2aa2740 --- /dev/null +++ b/engine/schema/src/com/cloud/network/dao/SslCertVO.java @@ -0,0 +1,132 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + + +import com.cloud.network.lb.SslCert; +import com.cloud.utils.db.Encrypt; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.InternalIdentity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.UUID; + +@Entity +@Table(name="sslcerts") +public class SslCertVO implements SslCert { + + @Id + @Column(name="id") + private Long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="certificate",length=16384) + private String certificate; + + + @Column(name="chain",length=2097152) + private String chain; + + @Encrypt + @Column(name="key",length=16384) + private String key; + + @Encrypt + @Column(name="password") + private String password; + + @Column(name="account_id") + private Long accountId; + + @Column(name = "domain_id") + long domainId; + + @Column(name = "fingerprint") + String fingerPrint; + + + + + public SslCertVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public SslCertVO(String cert, String key, String password, String chain, Long accountId, Long domainId, String fingerPrint) { + this.certificate = cert; + this.key = key; + this.chain = chain; + this.password = password; + this.accountId = accountId; + this.domainId = domainId; + this.fingerPrint = fingerPrint; + this.uuid = UUID.randomUUID().toString(); + } + + + // Getters + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public String getCertificate() { + return certificate; + } + + + @Override + public String getKey() { + return key; + } + + + @Override + public String getChain() { + return chain; + } + + @Override + public long getAccountId() { + return accountId; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public long getDomainId() { + return domainId; + } + + @Override + public String getFingerPrint() { + return fingerPrint; + } +} \ No newline at end of file diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 5c6f2e7dd63..e049cece058 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -98,6 +98,7 @@ import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; import com.cloud.network.lb.dao.ElasticLbVmMapDao; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.RedundantState; @@ -290,6 +291,7 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements Elast private void createApplyLoadBalancingRulesCommands( List rules, DomainRouterVO elbVm, Commands cmds, long guestNetworkId) { + /* XXX: cert */ LoadBalancerTO[] lbs = new LoadBalancerTO[rules.size()]; int i = 0; for (LoadBalancingRule rule : rules) { @@ -302,7 +304,8 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements Elast int srcPort = rule.getSourcePortStart(); String uuid = rule.getUuid(); List destinations = rule.getDestinations(); - LoadBalancerTO lb = new LoadBalancerTO(uuid, elbIp, srcPort, protocol, algorithm, revoked, false, false, destinations); + LoadBalancerTO lb = new LoadBalancerTO(uuid, elbIp, srcPort, protocol, algorithm, revoked, + false, false, destinations); lbs[i++] = lb; } @@ -377,8 +380,9 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements Elast List policyList = _lbMgr.getStickinessPolicies(lb.getId()); List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); Ip sourceIp = _networkModel.getPublicIpAddress(lb.getSourceIpAddressId()).getAddress(); + LbSslCert sslCert = _lbMgr.getLbSslCert(lb.getId()); LoadBalancingRule loadBalancing = new LoadBalancingRule( - lb, dstList, policyList, hcPolicyList, sourceIp); + lb, dstList, policyList, hcPolicyList, sourceIp, sslCert, lb.getLbProtocol()); lbRules.add(loadBalancing); } return applyLBRules(elbVm, lbRules, network.getId()); @@ -664,7 +668,7 @@ public class ElasticLoadBalancerManagerImpl extends ManagerBase implements Elast result = _lbMgr.createPublicLoadBalancer(lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourcePortStart(), lb.getDefaultPortStart(), ipId.longValue(), lb.getProtocol(), - lb.getAlgorithm(), false, CallContext.current()); + lb.getAlgorithm(), false, CallContext.current(), lb.getLbProtocol()); } catch (NetworkRuleConflictException e) { s_logger.warn("Failed to create LB rule, not continuing with ELB deployment"); if (newIp) { diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java index b6269ebae9d..b9482b5a490 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java @@ -77,6 +77,7 @@ import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.network.router.VirtualRouter; diff --git a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java index 82f90fb9dbf..90d6a183eb2 100644 --- a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java +++ b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/InternalLBVMManagerTest.java @@ -212,7 +212,7 @@ public class InternalLBVMManagerTest extends TestCase { List vms = new ArrayList(); List rules = new ArrayList(); LoadBalancingRule rule = new LoadBalancingRule(null, null, - null, null, null); + null, null, null, null, null); rules.add(rule); try { @@ -232,7 +232,7 @@ public class InternalLBVMManagerTest extends TestCase { List rules = new ArrayList(); LoadBalancingRule rule = new LoadBalancingRule(null, null, - null, null, null); + null, null, null, null, null); rules.add(rule); try { @@ -252,7 +252,7 @@ public class InternalLBVMManagerTest extends TestCase { List rules = new ArrayList(); LoadBalancingRule rule = new LoadBalancingRule(null, null, - null, null, null); + null, null, null, null, null); rules.add(rule); try { @@ -272,7 +272,7 @@ public class InternalLBVMManagerTest extends TestCase { List rules = new ArrayList(); LoadBalancingRule rule = new LoadBalancingRule(null, null, - null, null, null); + null, null, null, null, null); rules.add(rule); try { diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index 8101864840b..de3d7e86665 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -161,6 +161,7 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl @Inject ExternalLoadBalancerDeviceDao _externalLoadBalancerDeviceDao; + private boolean canHandle(Network config, Service service) { DataCenter zone = _dcDao.findById(config.getDataCenterId()); boolean handleInAdvanceZone = (zone.getNetworkType() == NetworkType.Advanced && @@ -277,7 +278,7 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl // Supports only Public load balancing lbCapabilities.put(Capability.LbSchemes, LoadBalancerContainer.Scheme.Public.toString()); - + // Specifies that load balancing rules can support autoscaling and the list of counters it supports AutoScaleCounter counter; List counterList = new ArrayList(); @@ -319,6 +320,10 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl staticNatCapabilities.put(Capability.ElasticIp, "true"); capabilities.put(Service.StaticNat, staticNatCapabilities); + // Supports SSL offloading + lbCapabilities.put(Capability.SslTermination, "true"); + + // TODO - Murali, please put correct capabilities here Map firewallCapabilities = new HashMap(); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); @@ -516,6 +521,7 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl cmdList.add(DeleteNetscalerLoadBalancerCmd.class); cmdList.add(ListNetscalerLoadBalancerNetworksCmd.class); cmdList.add(ListNetscalerLoadBalancersCmd.class); + return cmdList; } @@ -732,7 +738,8 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl List destinations = rule.getDestinations(); if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) { - LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies()); + LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, + rule.getStickinessPolicies(), rule.getHealthCheckPolicies(), rule.getLbSslCert(), rule.getLbProtocol()); if (rule.isAutoScaleConfig()) { loadBalancer.setAutoScaleVmGroup(rule.getAutoScaleVmGroup()); } @@ -894,7 +901,7 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) { LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, - false, false, destinations, null, rule.getHealthCheckPolicies()); + false, false, destinations, null, rule.getHealthCheckPolicies(), rule.getLbSslCert(), rule.getLbProtocol()); loadBalancersToApply.add(loadBalancer); } } @@ -1024,5 +1031,4 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl } return true; } - } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java index fe072e13718..e48d31d3f0a 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java @@ -25,6 +25,10 @@ import java.util.Map; import javax.naming.ConfigurationException; +import com.citrix.netscaler.nitro.resource.config.ssl.sslcertkey; +import com.citrix.netscaler.nitro.resource.config.ssl.sslvserver_sslcertkey_binding; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; +import com.cloud.utils.ssh.SshHelper; import org.apache.log4j.Logger; import com.citrix.netscaler.nitro.exception.nitro_exception; @@ -235,6 +239,7 @@ public class NetscalerResource implements ServerResource { //enable load balancing feature enableLoadBalancingFeature(); + SSL.enableSslFeature(_netscalerService); //if the the device is cloud stack provisioned then make it part of the public network if (_cloudManaged) { @@ -550,6 +555,8 @@ public class NetscalerResource implements ServerResource { String lbAlgorithm = loadBalancer.getAlgorithm(); String nsVirtualServerName = generateNSVirtualServerName(srcIp, srcPort); String nsMonitorName = generateNSMonitorName(srcIp, srcPort); + LbSslCert sslCert = loadBalancer.getSslCert(); + if(loadBalancer.isAutoScaleVmGroupTO()) { applyAutoScaleConfig(loadBalancer); // Continue to process all the rules. @@ -558,6 +565,7 @@ public class NetscalerResource implements ServerResource { boolean hasMonitor = false; boolean deleteMonitor = false; boolean destinationsToAdd = false; + boolean deleteCert = false; for (DestinationTO destination : loadBalancer.getDestinations()) { if (!destination.isRevoked()) { destinationsToAdd = true; @@ -655,9 +663,35 @@ public class NetscalerResource implements ServerResource { } } + + + if(sslCert != null && lbProtocol.equals(NetUtils.SSL_PROTO)) { + if ( sslCert.isRevoked() ){ + deleteCert = true; + } else{ + + String certName = generateSslCertName(srcIp, srcPort); + String keyName = generateSslKeyName(srcIp, srcPort); + String certKeyName = generateSslCertKeyName(srcIp, srcPort); + + if ( SSL.isSslCertKeyPresent(_netscalerService, certKeyName)){ + SSL.deleteSslCertKey(_netscalerService, certKeyName); + } + + + SSL.uploadCert(_ip, _username, _password, certName, sslCert.getCert().getBytes()); + SSL.uploadKey(_ip, _username, _password, keyName, sslCert.getKey().getBytes()); + + SSL.createSslCertKey(_netscalerService, certName, keyName, certKeyName, sslCert.getPassword()); + SSL.bindCertKeyToVserver(_netscalerService, certKeyName, nsVirtualServerName); + } + + } + if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully added LB destination: " + destination.getDestIp() + ":" + destination.getDestPort() + " to load balancer " + srcIp + ":" + srcPort); } + } else { // remove a destination from the deployed load balancing rule com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(_netscalerService, nsVirtualServerName); @@ -731,11 +765,27 @@ public class NetscalerResource implements ServerResource { } removeLBVirtualServer(nsVirtualServerName); deleteMonitor = true; + deleteCert = true; } } if(deleteMonitor) { removeLBMonitor(nsMonitorName); } + if ( sslCert != null && deleteCert){ + + String certName = generateSslCertName(srcIp, srcPort); + String keyName = generateSslKeyName(srcIp, srcPort); + String certKeyName = generateSslCertKeyName(srcIp, srcPort); + + // unbind before deleting + if ( nsVirtualServerExists(nsVirtualServerName) ){ + SSL.unbindCertKeyFromVserver(_netscalerService, certKeyName, nsVirtualServerName); + } + + SSL.deleteSslCertKey(_netscalerService, certKeyName); + SSL.deleteCertFile(_ip, _username, _password, certName); + SSL.deleteKeyFile(_ip, _username, _password, keyName); + } } @@ -1666,6 +1716,173 @@ public class NetscalerResource implements ServerResource { } } + /* SSL Termination */ + private static class SSL { + + private static final String SSL_CERT_PATH = "/nsconfig/ssl/"; + private static final int SSH_PORT = 22; + + private static boolean isSslCertKeyPresent(nitro_service ns, String certKeyName) throws ExecutionException { + + String filter = "certkey:" + certKeyName; + + try { + if (sslcertkey.count_filtered(ns, filter) > 0) return true; + } catch (nitro_exception e){ + throw new ExecutionException("Failed to get certkey " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to get certkey " + e.getMessage()); + } + + return false; + } + + private static void deleteSslCertKey(nitro_service ns, String certKeyName) throws ExecutionException { + try { + + sslcertkey certkey = new sslcertkey(); + certkey.set_certkey(certKeyName); + sslcertkey.delete(ns, certkey); + + } catch (nitro_exception e){ + throw new ExecutionException("Failed to delete certkey " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to delete certkey " + e.getMessage()); + } + + } + + private static void deleteCertFile(String nsIp, String username, String password, String certName) throws Exception { + SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + certName); + } + + private static void deleteKeyFile(String nsIp, String username, String password, String keyName) throws Exception { + SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + keyName); + } + + private static void createSslCertKey(nitro_service ns, String certName, String keyName, String certKeyName, String password) throws ExecutionException { + s_logger.debug("Adding cert to netscaler"); + try { + sslcertkey certkey = new sslcertkey(); + certkey.set_certkey(certKeyName); + certkey.set_cert(SSL_CERT_PATH + certName); + certkey.set_key(SSL_CERT_PATH + keyName); + + if( password != null ) { + certkey.set_passplain(password); + } + + certkey.perform_operation(ns); + + } catch (nitro_exception e){ + throw new ExecutionException("Failed to add certkey binding " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to add certkey binding " + e.getMessage()); + } + + } + + public static void updateCertKey(nitro_service ns, String certKeyName, String cert, String key, String password) throws ExecutionException { + try{ + sslcertkey certkey = sslcertkey.get(ns, certKeyName); + if ( cert != null ) + certkey.set_cert(cert); + if ( key != null ) + certkey.set_key(cert); + if ( password != null ) + certkey.set_passplain(cert); + + sslcertkey.change(ns,certkey); + + } catch (nitro_exception e){ + throw new ExecutionException("Failed to update ssl on load balancer due to " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to update ssl on load balancer due to " + e.getMessage()); + } + } + + private static void bindCertKeyToVserver(nitro_service ns, String certKeyName, String vserver) throws ExecutionException { + s_logger.debug("Adding cert to netscaler"); + + try { + sslvserver_sslcertkey_binding cert_binding = new sslvserver_sslcertkey_binding(); + cert_binding.set_certkeyname(certKeyName); + cert_binding.set_vservername(vserver); + cert_binding.perform_operation(ns); + } catch (nitro_exception e){ + throw new ExecutionException("Failed to bind certkey to vserver due to " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to bind certkey to vserver due to " + e.getMessage()); + } + } + + private static void unbindCertKeyFromVserver(nitro_service ns, String certKeyName, String vserver) throws ExecutionException { + try { + + sslvserver_sslcertkey_binding cert_binding = new sslvserver_sslcertkey_binding(); + cert_binding.set_certkeyname(certKeyName); + cert_binding.set_vservername(vserver); + sslvserver_sslcertkey_binding.delete(ns,cert_binding); + + } catch (nitro_exception e){ + throw new ExecutionException("Failed to unbind certkey to vserver due to " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to unbind certkey to vserver due to " + e.getMessage()); + } + + } + + + private static void uploadCert(String nsIp, String user, String password, String certName, byte[] certData) throws ExecutionException { + try { + SshHelper.scpTo(nsIp,SSH_PORT,user,null,password, SSL_CERT_PATH, certData, certName, null); + } catch (Exception e){ + throw new ExecutionException("Failed to copy private key to device " + e.getMessage()); + } + } + + private static void uploadKey(String nsIp, String user, String password, String keyName, byte[] keyData) throws ExecutionException { + try { + SshHelper.scpTo(nsIp, SSH_PORT, user, null, password, SSL_CERT_PATH, keyData, keyName, null); + } catch (Exception e){ + throw new ExecutionException("Failed to copy private key to device " + e.getMessage()); + } + } + + + private static void enableSslFeature(nitro_service ns) throws ExecutionException { + try { + base_response result = ns.enable_features(new String[]{"SSL"}); + if( result.errorcode != 0 ) + throw new ExecutionException("Unable to enable SSL on LB"); + } catch (nitro_exception e){ + throw new ExecutionException("Failed to enable ssl feature on load balancer due to " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to enable ssl feature on load balancer due to " + e.getMessage()); + } + } + + public static boolean checkSslFeature(nitro_service ns) throws ExecutionException { + try { + String[] features = ns.get_enabled_features(); + if (features != null) { + for (String feature : features) { + if (feature.equalsIgnoreCase("SSL")) { + return true; + } + } + } + return false; + } catch (nitro_exception e){ + throw new ExecutionException("Failed to check ssl feature on load balancer due to " + e.getMessage()); + } catch (Exception e){ + throw new ExecutionException("Failed to check ssl feature on load balancer due to " + e.getMessage()); + } + } + + + } + private void enableVPXInterfaces(String publicIf, String privateIf, ns ns_obj) { // enable VPX to use 10 gigabit Ethernet interfaces if public/private interface @@ -2110,6 +2327,25 @@ public class NetscalerResource implements ServerResource { } } + private boolean nsVirtualServerExists(String vserverName) throws ExecutionException { + try { + if (com.citrix.netscaler.nitro.resource.config.lb.lbvserver.get(_netscalerService, vserverName) != null) { + return true; + } else { + return false; + } + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return false; + } else { + throw new ExecutionException("Failed to verify VServer " + vserverName + " exists on the NetScaler device due to " + e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException("Failed to verify VServer " + vserverName + " exists on the NetScaler device due to " + e.getMessage()); + } + } + + private boolean nsVlanNsipBindingExists(long vlanTag, String vlanSelfIp) throws ExecutionException { try { vlan_nsip_binding[] vlanNsipBindings = vlan_nsip_binding.get(_netscalerService, vlanTag); @@ -2308,11 +2544,14 @@ public class NetscalerResource implements ServerResource { private String getNetScalerProtocol(LoadBalancerTO loadBalancer) throws ExecutionException { String port = Integer.toString(loadBalancer.getSrcPort()); - String lbProtocol = loadBalancer.getProtocol(); + String lbProtocol = loadBalancer.getLbProtocol(); StickinessPolicyTO[] stickyPolicies = loadBalancer.getStickinessPolicies(); String nsProtocol = "TCP"; - if ((stickyPolicies != null) && (stickyPolicies.length > 0) && (stickyPolicies[0] != null)){ + if(lbProtocol == null) + lbProtocol = loadBalancer.getProtocol(); + + if ((stickyPolicies != null) && (stickyPolicies.length > 0) && (stickyPolicies[0] != null)){ StickinessPolicyTO stickinessPolicy = stickyPolicies[0]; if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) || (StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()))) { @@ -2321,6 +2560,10 @@ public class NetscalerResource implements ServerResource { } } + + if( lbProtocol.equalsIgnoreCase(NetUtils.SSL_PROTO) || lbProtocol.equalsIgnoreCase(NetUtils.HTTP_PROTO)) + return lbProtocol.toUpperCase(); + if (port.equals(NetUtils.HTTP_PORT)) { nsProtocol = "HTTP"; } else if (NetUtils.TCP_PROTO.equalsIgnoreCase(lbProtocol)) { @@ -3381,6 +3624,18 @@ public class NetscalerResource implements ServerResource { return counterName.replace(' ', '_'); } + private String generateSslCertName(String srcIp, long srcPort) { + // maximum length supported by NS is 31 + return genObjectName("Cloud-Cert", srcIp, srcPort); + } + + private String generateSslKeyName(String srcIp, long srcPort) { + return genObjectName("Cloud-Key", srcIp, srcPort); + } + private String generateSslCertKeyName(String srcIp, long srcPort) { + return genObjectName("Cloud-CertKey", srcIp, srcPort); + } + private String genObjectName(Object... args) { String objectName = ""; for (int i = 0; i < args.length; i++) { diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml index 5e3790825cb..f7a8d6795cd 100644 --- a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml +++ b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml @@ -223,4 +223,6 @@ + + diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index 6ca40c01e98..8d54541dd62 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -899,7 +899,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) { boolean inline = _networkMgr.isNetworkInlineMode(network); LoadBalancerTO loadBalancer = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, false, inline, destinations, rule.getStickinessPolicies(), - rule.getHealthCheckPolicies()); + rule.getHealthCheckPolicies(), rule.getLbSslCert(), rule.getLbProtocol()); if (rule.isAutoScaleConfig()) { loadBalancer.setAutoScaleVmGroup(rule.getAutoScaleVmGroup()); } @@ -1184,7 +1184,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase if ((destinations != null && !destinations.isEmpty()) || !rule.isAutoScaleConfig()) { boolean inline = _networkMgr.isNetworkInlineMode(network); LoadBalancerTO loadBalancer = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, - false, inline, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies()); + false, inline, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies(), rule.getLbSslCert(), rule.getLbProtocol()); loadBalancersToApply.add(loadBalancer); } } @@ -1218,5 +1218,5 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase } } return null; - } + } } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 0d434784505..a1650e07109 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -107,6 +107,9 @@ import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.LoadBalancerCertMapDao; +import com.cloud.network.dao.LoadBalancerCertMapVO; +import com.cloud.network.dao.SslCertVO; import com.cloud.network.element.LoadBalancingServiceProvider; import com.cloud.network.lb.LoadBalancingRule.LbAutoScalePolicy; import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmGroup; @@ -115,6 +118,7 @@ import com.cloud.network.lb.LoadBalancingRule.LbCondition; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; import com.cloud.network.rules.FirewallManager; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.FirewallRuleType; @@ -253,6 +257,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements IpAddressManager _ipAddrMgr; @Inject EntityManager _entityMgr; + @Inject + LoadBalancerCertMapDao _lbCertMapDao; + // Will return a string. For LB Stickiness this will be a json, for // autoscale this will be "," separated values @@ -350,7 +357,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements */ List policyList = getStickinessPolicies(lb.getId()); Ip sourceIp = getSourceIp(lb); - LoadBalancingRule rule = new LoadBalancingRule(lb, null, policyList, null, sourceIp); + LoadBalancingRule rule = new LoadBalancingRule(lb, null, policyList, null, sourceIp, null, lb.getLbProtocol()); rule.setAutoScaleVmGroup(lbAutoScaleVmGroup); if (!isRollBackAllowedForProvider(lb)) { @@ -558,7 +565,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements policyList.add(new LbStickinessPolicy(cmd.getStickinessMethodName(), lbpolicy.getParams())); Ip sourceIp = getSourceIp(loadBalancer); LoadBalancingRule lbRule = new LoadBalancingRule(loadBalancer, getExistingDestinations(lbpolicy.getId()), - policyList, null, sourceIp); + policyList, null, sourceIp,null, loadBalancer.getLbProtocol()); if (!validateLbRule(lbRule)) { throw new InvalidParameterValueException("Failed to create Stickiness policy: Validation Failed " + cmd.getLbRuleId()); @@ -905,7 +912,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements // hashealtChecks if (hcPolicyList != null && hcPolicyList.size() > 0) { Ip sourceIp = getSourceIp(lb); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, null, hcPolicyList, sourceIp); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, null, hcPolicyList, sourceIp, null, lb.getLbProtocol()); lbrules.add(loadBalancing); } } @@ -1087,12 +1094,161 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return success; } + @Override + public boolean assignSSLCertToLoadBalancerRule(Long lbId, String certName, String publicCert, String privateKey) { + s_logger.error("Calling the manager for LB"); + LoadBalancerVO loadBalancer = _lbDao.findById(lbId); + + return false; //TODO + } + @Override @ActionEvent(eventType = EventTypes.EVENT_REMOVE_FROM_LOAD_BALANCER_RULE, eventDescription = "removing from load balancer", async = true) public boolean removeFromLoadBalancer(long loadBalancerId, List instanceIds) { return removeFromLoadBalancerInternal(loadBalancerId, instanceIds, true); } + @Override + public LbSslCert getLbSslCert(long lbRuleId) { + LoadBalancerCertMapVO lbCertMap = _lbCertMapDao.findByLbRuleId(lbRuleId); + + if ( lbCertMap == null) + return null; + + SslCertVO certVO = _entityMgr.findById(SslCertVO.class, lbCertMap.getCertId()); + if ( certVO == null) { + s_logger.warn("Cert rule with cert ID " + lbCertMap.getCertId() + " but Cert is not found"); + return null; + } + + return new LbSslCert(certVO.getCertificate(), certVO.getKey(), + certVO.getChain(), certVO.getPassword(), lbCertMap.isRevoke()); + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_LB_CERT_ASSIGN, eventDescription = "assigning certificate to load balancer", async = true) + public boolean assignCertToLoadBalancer(long lbRuleId, Long certId) { + CallContext caller = CallContext.current(); + + LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(lbRuleId)); + if (loadBalancer == null) { + throw new InvalidParameterException("Invalid load balancer id: " + lbRuleId); + } + + SslCertVO certVO = _entityMgr.findById(SslCertVO.class,certId); + if (certVO == null) { + throw new InvalidParameterException("Invalid certificate id: " + certId); + } + + _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + + // check if LB and Cert belong to the same account + if( loadBalancer.getAccountId() != certVO.getAccountId() ){ + throw new InvalidParameterValueException("Access denied for account " + certVO.getAccountId()); + } + + + String capability = getLBCapability(loadBalancer.getNetworkId(), Capability.SslTermination.getName()); + if ( capability == null){ + throw new InvalidParameterValueException("Ssl termination not supported by the loadbalancer"); + } + + //check if the lb is already bound + LoadBalancerCertMapVO certMapRule = _lbCertMapDao.findByLbRuleId(loadBalancer.getId()); + if (certMapRule != null) + throw new InvalidParameterValueException("Another certificate is already bound to the LB"); + + //check for correct port + if ( loadBalancer.getLbProtocol() == null || !(loadBalancer.getLbProtocol().equals(NetUtils.SSL_PROTO))) + throw new InvalidParameterValueException("Bad LB protocol: Expected ssl got " + loadBalancer.getLbProtocol()); + + + boolean success = false; + FirewallRule.State backupState = loadBalancer.getState(); + + try { + + loadBalancer.setState(FirewallRule.State.Add); + _lbDao.persist(loadBalancer); + LoadBalancerCertMapVO certMap = new LoadBalancerCertMapVO(lbRuleId,certId,false); + _lbCertMapDao.persist(certMap); + applyLoadBalancerConfig(loadBalancer.getId()); + /*s_logger.warn("Failed to apply Ssl Cert to LB " + loadBalancer.getId()); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to apply Ssl Cert to LB " + loadBalancer.getId()); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); + throw ex;*/ + success = true; + } catch (ResourceUnavailableException e) { + if (isRollBackAllowedForProvider(loadBalancer)) { + + loadBalancer.setState(backupState); + _lbDao.persist(loadBalancer); + LoadBalancerCertMapVO certMap = _lbCertMapDao.findByLbRuleId(lbRuleId); + _lbCertMapDao.remove(certMap.getId()); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " while adding cert"); + } + s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); + } + return success; + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_LB_CERT_REMOVE, eventDescription = "removing certificate from load balancer", async = true) + public boolean removeCertFromLoadBalancer(long lbRuleId) { + CallContext caller = CallContext.current(); + + LoadBalancerVO loadBalancer = _lbDao.findById(lbRuleId); + LoadBalancerCertMapVO lbCertMap = _lbCertMapDao.findByLbRuleId(lbRuleId); + + if (loadBalancer == null) { + throw new InvalidParameterException("Invalid load balancer value: " + lbRuleId); + } + + if( lbCertMap == null ) { + throw new InvalidParameterException("No certificate is bound to lb with id: " + lbRuleId); + } + + _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + + boolean success = false; + FirewallRule.State backupState = loadBalancer.getState(); + try { + + loadBalancer.setState(FirewallRule.State.Add); + _lbDao.persist(loadBalancer); + lbCertMap.setRevoke(true); + _lbCertMapDao.persist(lbCertMap); + + if (!applyLoadBalancerConfig(lbRuleId)) { + s_logger.warn("Failed to remove cert from load balancer rule id " + lbRuleId); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to remove certificate load balancer rule id " + lbRuleId); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); + throw ex; + } + success = true; + } catch (ResourceUnavailableException e) { + if (isRollBackAllowedForProvider(loadBalancer)) { + lbCertMap.setRevoke(false); + _lbCertMapDao.persist(lbCertMap); + loadBalancer.setState(backupState); + _lbDao.persist(loadBalancer); + s_logger.debug("Rolled back certificate removal lb id " + lbRuleId); + } + s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); + if (!success) { + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to remove certificate from load balancer rule id " + lbRuleId); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); + throw ex; + } + } + return success; + } + private boolean removeFromLoadBalancerInternal(long loadBalancerId, List instanceIds, boolean rollBack) { CallContext caller = CallContext.current(); @@ -1317,7 +1473,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Override @ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer") public LoadBalancer createPublicLoadBalancerRule(String xId, String name, String description, - int srcPortStart, int srcPortEnd, int defPortStart, int defPortEnd, Long ipAddrId, String protocol, String algorithm, long networkId, long lbOwnerId, boolean openFirewall) + int srcPortStart, int srcPortEnd, int defPortStart, int defPortEnd, Long ipAddrId, String protocol, String algorithm, + long networkId, long lbOwnerId, boolean openFirewall, String lbProtocol) throws NetworkRuleConflictException, InsufficientAddressCapacityException { Account lbOwner = _accountMgr.getAccount(lbOwnerId); @@ -1377,7 +1534,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements + network); } - result = createPublicLoadBalancer(xId, name, description, srcPortStart, defPortStart, ipVO.getId(), protocol, algorithm, openFirewall, CallContext.current()); + result = createPublicLoadBalancer(xId, name, description, srcPortStart, defPortStart, ipVO.getId(), protocol, + algorithm, openFirewall, CallContext.current(), lbProtocol); } catch (Exception ex) { s_logger.warn("Failed to create load balancer due to ", ex); if (ex instanceof NetworkRuleConflictException) { @@ -1407,13 +1565,14 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @DB @Override public LoadBalancer createPublicLoadBalancer(final String xId, final String name, final String description, - final int srcPort, final int destPort, final long sourceIpId, final String protocol, final String algorithm, final boolean openFirewall, final CallContext caller) + final int srcPort, final int destPort, final long sourceIpId, final String protocol, + final String algorithm, final boolean openFirewall, final CallContext caller, final String lbProtocol) throws NetworkRuleConflictException { if (!NetUtils.isValidPort(destPort)) { throw new InvalidParameterValueException("privatePort is an invalid value: " + destPort); } - + if ((algorithm == null) || !NetUtils.isValidAlgorithm(algorithm)) { throw new InvalidParameterValueException("Invalid algorithm: " + algorithm); } @@ -1454,18 +1613,29 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements _firewallMgr.validateFirewallRule(caller.getCallingAccount(), ipAddr, srcPort, srcPort, protocol, Purpose.LoadBalancing, FirewallRuleType.User, networkId, null); + LoadBalancerVO newRule = new LoadBalancerVO(xId, name, description, + sourceIpId, srcPort, destPort, algorithm, + networkId, ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId(), lbProtocol); + + // verify rule is supported by Lb provider of the network + Ip sourceIp = getSourceIp(newRule); + LoadBalancingRule loadBalancing = new LoadBalancingRule(newRule, new ArrayList(), + new ArrayList(), new ArrayList(), sourceIp, null, lbProtocol); + if (!validateLbRule(loadBalancing)) { + throw new InvalidParameterValueException("LB service provider cannot support this rule"); + } return Transaction.execute(new TransactionCallbackWithException() { @Override public LoadBalancerVO doInTransaction(TransactionStatus status) throws NetworkRuleConflictException { LoadBalancerVO newRule = new LoadBalancerVO(xId, name, description, sourceIpId, srcPort, destPort, algorithm, - networkId, ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId()); + networkId, ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId(), lbProtocol); // verify rule is supported by Lb provider of the network Ip sourceIp = getSourceIp(newRule); LoadBalancingRule loadBalancing = new LoadBalancingRule(newRule, new ArrayList(), - new ArrayList(), new ArrayList(), sourceIp); + new ArrayList(), new ArrayList(), sourceIp, null, lbProtocol); if (!validateLbRule(loadBalancing)) { throw new InvalidParameterValueException("LB service provider cannot support this rule"); } @@ -1510,7 +1680,6 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } - @Override public boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException { LoadBalancerVO lb = _lbDao.findById(lbRuleId); List lbs; @@ -1576,7 +1745,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements List policyList = getStickinessPolicies(lb.getId()); Ip sourceIp = getSourceIp(lb); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, null, policyList, null, sourceIp); + LbSslCert sslCert = getLbSslCert(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, null, policyList, null, sourceIp, sslCert, lb.getLbProtocol()); if (_autoScaleVmGroupDao.isAutoScaleLoadBalancer(lb.getId())) { // Get the associated VmGroup @@ -1659,7 +1829,13 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements _lb2healthcheckDao.remove(lb.getId(), true); s_logger.debug("Load balancer rule id " + lb.getId() + " is removed health check monitors policies"); } - + + LoadBalancerCertMapVO lbCertMap = _lbCertMapDao.findByLbRuleId(lb.getId()); + if (lbCertMap != null && lbCertMap.isRevoke()) { + _lbCertMapDao.remove(lbCertMap.getId()); + s_logger.debug("Load balancer rule id " + lb.getId() + " removed certificate mapping"); + } + return checkForReleaseElasticIp; } }); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 617d6ac8f3e..b8d0babe3f9 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -187,6 +187,7 @@ import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.lb.LoadBalancingRule.LbSslCert; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.network.router.VirtualRouter.Role; @@ -2544,7 +2545,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V List policyList = _lbMgr.getStickinessPolicies(lb.getId()); List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); Ip sourceIp = _networkModel.getPublicIpAddress(lb.getSourceIpAddressId()).getAddress(); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList, sourceIp); + LbSslCert sslCert = _lbMgr.getLbSslCert(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList, sourceIp, sslCert, lb.getLbProtocol()); lbRules.add(loadBalancing); } } @@ -3680,8 +3682,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); + LbSslCert sslCert = _lbMgr.getLbSslCert(lb.getId()); Ip sourceIp = _networkModel.getPublicIpAddress(lb.getSourceIpAddressId()).getAddress(); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList, sourceIp); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList, sourceIp, + sslCert, lb.getLbProtocol()); + lbRules.add(loadBalancing); } return sendLBRules(router, lbRules, network.getId()); @@ -3716,8 +3721,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); + LbSslCert sslCert = _lbMgr.getLbSslCert(lb.getId()); Ip sourceIp = _networkModel.getPublicIpAddress(lb.getSourceIpAddressId()).getAddress(); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList, sourceIp); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList, sourceIp, sslCert, lb.getLbProtocol()); lbRules.add(loadBalancing); } return sendLBRules(router, lbRules, network.getId()); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 35bc6813c03..d083c11eceb 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -287,6 +287,11 @@ import org.apache.cloudstack.api.command.user.loadbalancer.ListLoadBalancerRuleI import org.apache.cloudstack.api.command.user.loadbalancer.ListLoadBalancerRulesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.RemoveFromLoadBalancerRuleCmd; import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.UploadSslCertCmd; +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.AssignCertToLoadBalancerCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.RemoveCertFromLoadBalancerCmd; import org.apache.cloudstack.api.command.user.nat.CreateIpForwardingRuleCmd; import org.apache.cloudstack.api.command.user.nat.DeleteIpForwardingRuleCmd; import org.apache.cloudstack.api.command.user.nat.DisableStaticNatCmd; @@ -2876,6 +2881,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(UpdateNetworkACLItemCmd.class); cmdList.add(CleanVMReservationsCmd.class); cmdList.add(UpgradeRouterTemplateCmd.class); + cmdList.add(UploadSslCertCmd.class); + cmdList.add(DeleteSslCertCmd.class); + cmdList.add(ListSslCertsCmd.class); + cmdList.add(AssignCertToLoadBalancerCmd.class); + cmdList.add(RemoveCertFromLoadBalancerCmd.class); return cmdList; } diff --git a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java index b7cd231831c..f0f0a6efbf2 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -146,7 +146,7 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A //4) Validate Load Balancing rule on the providers LoadBalancingRule loadBalancing = new LoadBalancingRule(newRule, new ArrayList(), - new ArrayList(), new ArrayList(), sourceIpAddr); + new ArrayList(), new ArrayList(), sourceIpAddr, null, null); if (!_lbMgr.validateLbRule(loadBalancing)) { throw new InvalidParameterValueException("LB service provider cannot support this rule"); } diff --git a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java new file mode 100644 index 00000000000..53dae507bbb --- /dev/null +++ b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java @@ -0,0 +1,477 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.network.lb; + +import com.cloud.event.ActionEvent; +import com.cloud.event.EventTypes; +import com.cloud.network.dao.*; +import com.cloud.network.lb.CertService; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; +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 com.cloud.exception.InvalidParameterValueException; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.utils.db.DB; +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMReader; +import org.bouncycastle.openssl.PasswordFinder; + +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.IOException; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.security.*; +import java.security.cert.*; +import java.security.cert.Certificate; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Local(value = {CertService.class}) +public class CertServiceImpl implements CertService { + + private static final Logger s_logger = Logger.getLogger(CertServiceImpl.class); + + @Inject AccountManager _accountMgr; + @Inject AccountDao _accountDao; + @Inject SslCertDao _sslCertDao; + @Inject LoadBalancerCertMapDao _lbCertDao; + @Inject EntityManager _entityMgr; + + + + public CertServiceImpl() { + Security.addProvider(new BouncyCastleProvider()); + } + + @DB + @Override + @ActionEvent(eventType = EventTypes.EVENT_LB_CERT_UPLOAD, eventDescription = "Uploading a certificate to cloudstack", async = false) + public SslCertResponse uploadSslCert(UploadSslCertCmd certCmd) { + try { + + String cert = URLDecoder.decode(certCmd.getCert(), "UTF-8"); + String key = URLDecoder.decode(certCmd.getKey(), "UTF-8"); + String password = certCmd.getPassword(); + String chain = certCmd.getChain() == null ? null: URLDecoder.decode(certCmd.getChain(), "UTF-8"); + + validate(cert, key, password, chain); + s_logger.debug("Certificate Validation succeeded"); + String fingerPrint = generateFingerPrint(parseCertificate(cert)); + + Long accountId = CallContext.current().getCallingAccount().getId(); + Long domainId = CallContext.current().getCallingAccount().getDomainId(); + + + SslCertVO certVO = new SslCertVO(cert, key, password, chain, accountId, domainId, fingerPrint); + _sslCertDao.persist(certVO); + + + return createCertResponse(certVO, null); + + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("Error decoding certificate data"); + } + + } + + @DB + @Override + @ActionEvent(eventType = EventTypes.EVENT_LB_CERT_DELETE, eventDescription = "Deleting a certificate to cloudstack", async = false) + public void deleteSslCert(DeleteSslCertCmd deleteSslCertCmd) { + + CallContext ctx = CallContext.current(); + Account caller = ctx.getCallingAccount(); + + Long certId = deleteSslCertCmd.getId(); + SslCertVO certVO = _sslCertDao.findById(certId); + + if (certVO == null) { + throw new InvalidParameterValueException("Invalid certificate id: " + certId); + } + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ModifyEntry, true, certVO); + + List lbCertRule = _lbCertDao.listByCertId(certId); + + if ( (lbCertRule != null) && (!lbCertRule.isEmpty()) ){ + String lbUuids = ""; + + for( LoadBalancerCertMapVO rule : lbCertRule ){ + LoadBalancerVO lb = _entityMgr.findById(LoadBalancerVO.class, rule.getLbId()); + lbUuids += " " + lb.getUuid(); + } + + throw new CloudRuntimeException("Certificate in use by a loadbalancer(s)" + lbUuids); + } + + _sslCertDao.remove(certId); + } + + @Override + public List listSslCerts(ListSslCertsCmd listSslCertCmd) { + CallContext ctx = CallContext.current(); + Account caller = ctx.getCallingAccount(); + + Long certId= listSslCertCmd.getCertId(); + Long accountId = listSslCertCmd.getAccountId(); + Long lbRuleId = listSslCertCmd.getLbId(); + + List certResponseList = new ArrayList(); + + if (certId == null && accountId == null && lbRuleId == null ) { + throw new InvalidParameterValueException("Invalid parameters either certificate ID or Account ID or Loadbalancer ID required"); + } + + List certLbMap = null; + SslCertVO certVO = null; + + + if(certId != null) { + + certVO = _sslCertDao.findById(certId); + + if (certVO == null) { + throw new InvalidParameterValueException("Invalid certificate id: " + certId); + } + + + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ListEntry, true, certVO); + + certLbMap = _lbCertDao.listByCertId(certId); + + certResponseList.add(createCertResponse(certVO, certLbMap)); + return certResponseList; + } + + if ( lbRuleId != null) { + LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, lbRuleId); + + if ( lb == null ){ + throw new InvalidParameterValueException("found no loadbalancer wth id: " + lbRuleId); + } + + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ListEntry, true, lb); + + // get the cert id + LoadBalancerCertMapVO lbCertMapRule; + lbCertMapRule = _lbCertDao.findByLbRuleId(lbRuleId); + + if (lbCertMapRule == null) { + throw new InvalidParameterValueException("No certificate bound to loadbalancer id: " + lbRuleId); + } + + certVO = _sslCertDao.findById(lbCertMapRule.getCertId()); + certLbMap = _lbCertDao.listByCertId(lbCertMapRule.getCertId()); + + certResponseList.add(createCertResponse(certVO, certLbMap)); + return certResponseList; + + } + + //reached here look by accountId + List certVOList = _sslCertDao.listByAccountId(accountId); + if ( certVOList == null || certVOList.isEmpty()) + return certResponseList; + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ListEntry, true, certVOList.get(0)); + + for( SslCertVO cert : certVOList ){ + certLbMap = _lbCertDao.listByCertId(cert.getId()); + certResponseList.add(createCertResponse(cert, certLbMap)); + } + + return certResponseList; + } + + + private void validate(String _cert, String _key, String _password, String _chain) { + Certificate cert; + PrivateKey key; + List chain=null; + + + try { + cert = parseCertificate(_cert); + key = parsePrivateKey(_key, _password); + + if ( _chain != null) { + chain = parseChain(_chain); + } + + } catch (IOException e) { + throw new IllegalArgumentException("Parsing certificate/key failed: " + e.getMessage()); + } + + validateCert(cert, _chain != null? true: false); + validateKeys(cert.getPublicKey(), key); + + if ( _chain != null ) + validateChain(chain, cert); + } + + public SslCertResponse createCertResponse(SslCertVO cert, List lbCertMap) { + SslCertResponse response = new SslCertResponse(); + + Account account = _accountDao.findByIdIncludingRemoved(cert.getAccountId()); + + response.setObjectName("sslcert"); + response.setId(cert.getUuid()); + response.setCertificate(cert.getCertificate()); + response.setPrivatekey(cert.getKey()); + response.setFingerprint(cert.getFingerPrint()); + response.setAccountName(account.getAccountName()); + + if ( cert.getChain() != null) + response.setCertchain(cert.getChain()); + + if ( lbCertMap != null && !lbCertMap.isEmpty()){ + List lbIds = new ArrayList(); + for ( LoadBalancerCertMapVO mapVO : lbCertMap ) { + LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, mapVO.getLbId()); + lbIds.add(lb.getUuid()); + } + response.setLbIds(lbIds); + } + + return response; + } + + private void validateCert(Certificate cert, boolean chain_present) { + + if ( !( cert instanceof X509Certificate)) + throw new IllegalArgumentException("Invalid certificate format. Expected X509 certificate"); + + try { + ((X509Certificate)cert).checkValidity(); + } catch (Exception e) { + throw new IllegalArgumentException("Certificate expired or not valid"); + } + + if( !chain_present ) { + PublicKey pubKey = cert.getPublicKey(); + try { + cert.verify(pubKey); + } catch (Exception e) { + throw new IllegalArgumentException("No chain given and certificate not self signed"); + } + } + } + + private void validateKeys(PublicKey pubKey, PrivateKey privKey) { + + if (pubKey.getAlgorithm() != privKey.getAlgorithm()) + throw new IllegalArgumentException("Public and private key have different algorithms"); + + // No encryption for DSA + if ( pubKey.getAlgorithm() != "RSA") + return; + + try { + + String data = "ENCRYPT_DATA"; + SecureRandom random = new SecureRandom(); + Cipher cipher = Cipher.getInstance(pubKey.getAlgorithm()); + cipher.init(Cipher.ENCRYPT_MODE,privKey,random); + byte[] encryptedData = cipher.doFinal(data.getBytes()); + + cipher.init(Cipher.DECRYPT_MODE,pubKey,random); + String decreptedData = new String(cipher.doFinal(encryptedData)); + if (!decreptedData.equals(data)) + throw new IllegalArgumentException("Bad public-private key"); + + } catch (BadPaddingException e) { + throw new IllegalArgumentException("Bad public-private key"); + } catch (IllegalBlockSizeException e) { + throw new IllegalArgumentException("Bad public-private key"); + } catch (NoSuchPaddingException e) { + throw new IllegalArgumentException("Bad public-private key"); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("Invalid public-private key"); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Invalid algorithm for public-private key"); + } + } + + + private void validateChain(List chain, Certificate cert) { + + List certs = new ArrayList(); + List root = new ArrayList(); + + Set anchors = new HashSet(); + + + certs.add(cert); // adding for self signed certs + certs.addAll(chain); + + for( Certificate c : certs) { + if ( !( c instanceof X509Certificate)) + throw new IllegalArgumentException("Invalid chain format. Expected X509 certificate"); + + X509Certificate xCert = (X509Certificate)c; + + Principal subject = xCert.getSubjectDN(); + Principal issuer = xCert.getIssuerDN(); + + if( issuer != null && subject.equals(issuer) ) { + root.add(c); + anchors.add(new TrustAnchor(xCert,null)); + } + } + + if ( root.size() == 0 ) + throw new IllegalArgumentException("No root certificates found for certificate chain",null); + + + X509CertSelector target = new X509CertSelector(); + target.setCertificate((X509Certificate)cert); + + PKIXBuilderParameters params = null; + try { + params = new PKIXBuilderParameters(anchors, target); + params.setRevocationEnabled(false); + params.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certs))); + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); + builder.build(params); + } catch (InvalidAlgorithmParameterException e) { + throw new IllegalArgumentException("Invalid certificate chain",null); + } catch (CertPathBuilderException e) { + throw new IllegalArgumentException("Invalid certificate chain",null); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Invalid certificate chain",null); + } + + } + + public PrivateKey parsePrivateKey(String key, String password) throws IOException { + + PasswordFinder pGet = null; + + if( password != null ) + pGet = new KeyPassword(password.toCharArray()); + + PEMReader privateKey = new PEMReader(new StringReader(key), pGet); + Object obj = privateKey.readObject(); + + try { + + if ( obj instanceof KeyPair ) + return ((KeyPair)obj).getPrivate(); + + return (PrivateKey) obj; + + }catch (Exception e){ + e.printStackTrace(); + throw new IOException("Invalid Key format or invalid password."); + } + } + + + public Certificate parseCertificate(String cert) { + PEMReader certPem = new PEMReader(new StringReader(cert)); + try { + return (Certificate) certPem.readObject(); + } catch (Exception e) { + throw new InvalidParameterValueException("Invalid Certificate format. Expected X509 certificate"); + } + } + + + public List parseChain(String chain) throws IOException { + + List certs = new ArrayList(); + 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",null); + + 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 password_requested=false; + char[] password; + + + KeyPassword(char[] word){ + this.password = word; + } + + public char[] getPassword() { + password_requested=true; + return password; + } + + public boolean getPasswordRequested(){ + return password_requested; + } + } +} \ No newline at end of file diff --git a/server/test/org/apache/cloudstack/lb/ApplicationLoadBalancerTest.java b/server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java similarity index 99% rename from server/test/org/apache/cloudstack/lb/ApplicationLoadBalancerTest.java rename to server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java index 9b46e683113..82b11817948 100644 --- a/server/test/org/apache/cloudstack/lb/ApplicationLoadBalancerTest.java +++ b/server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package org.apache.cloudstack.lb; +package org.apache.cloudstack.network.lb; import java.io.IOException; import java.lang.reflect.Field; @@ -25,6 +25,7 @@ import javax.inject.Inject; import junit.framework.TestCase; +import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -335,7 +336,7 @@ public class ApplicationLoadBalancerTest extends TestCase { public AccountManager accountManager() { return Mockito.mock(AccountManager.class); } - + @Bean public LoadBalancingRulesManager loadBalancingRulesManager() { diff --git a/server/test/org/apache/cloudstack/network/lb/CertServiceTest.java b/server/test/org/apache/cloudstack/network/lb/CertServiceTest.java new file mode 100644 index 00000000000..e47fc013f05 --- /dev/null +++ b/server/test/org/apache/cloudstack/network/lb/CertServiceTest.java @@ -0,0 +1,791 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.network.lb; + +import com.cloud.network.dao.*; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionLegacy; +import junit.framework.TestCase; +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.apache.log4j.Logger; +import org.junit.After; +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.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static org.apache.commons.io.FileUtils.readFileToString; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.when; + +public class CertServiceTest extends TestCase { + + private static final Logger s_logger = Logger.getLogger( CertServiceTest.class); + + @Override + @Before + public void setUp() { + 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()); + CallContext.register(user, account); + } + + @Override + @After + public void tearDown() { + CallContext.unregister(); + } + + @Test + public void testUploadSslCert() throws Exception { + + /* Test1 : Given a Certificate in bad format (Not PEM), upload should fail */ + runUploadSslCertBadFormat(); + + /* Test2: Given a Certificate which is not X509, upload should fail */ + runUploadSslCertNotX509(); + + /* Test3: Given an expired certificate, upload should fail */ + runUploadSslCertExpiredCert(); + + /* Test4: Given a private key which has a different algorithm than the certificate, + upload should fail. + */ + runUploadSslCertBadkeyAlgo(); + + /* Test5: Given a private key which does not match the public key in the certificate, + upload should fail + */ + runUploadSslCertBadkeyPair(); + + /* Test6: Given an encrypted private key with a bad password. Upload should fail. */ + runUploadSslCertBadPassword(); + + /* Test7: If no chain is given, the certificate should be self signed. Else, uploadShould Fail */ + runUploadSslCertNoChain(); + + /* Test8: Chain is given but does not have root certificate */ + runUploadSslCertNoRootCert(); + + /* Test9: The chain given is not the correct chain for the certificate */ + runUploadSslCertBadChain(); + + /* Test10: Given a Self-signed Certificate with encrypted key, upload should succeed */ + runUploadSslCertSelfSignedNoPassword(); + + /* Test11: Given a Self-signed Certificate with non-encrypted key, upload should succeed */ + runUploadSslCertSelfSignedWithPassword(); + + /* Test12: Given a certificate signed by a CA and a valid CA chain, upload should succeed */ + runUploadSslCertWithCAChain(); + + } + + private void runUploadSslCertWithCAChain() throws Exception { + //To change body of created methods use File | Settings | File Templates. + + TransactionLegacy txn = TransactionLegacy.open("runUploadSslCertWithCAChain"); + + String certFile = getClass().getResource("/certs/rsa_ca_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_ca_signed.key").getFile(); + String chainFile = getClass().getResource("/certs/root_chain.crt").getFile(); + String password = "user"; + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + String chain = URLEncoder.encode(readFileToString(new File(chainFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + + certService._accountDao = Mockito.mock(AccountDao.class); + when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); + + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + Field passField = _class.getDeclaredField("password"); + passField.setAccessible(true); + passField.set(uploadCmd, password); + + Field chainField = _class.getDeclaredField("chain"); + chainField.setAccessible(true); + chainField.set(uploadCmd, chain); + + certService.uploadSslCert(uploadCmd); + } + + private void runUploadSslCertSelfSignedWithPassword() throws Exception { + + TransactionLegacy txn = TransactionLegacy.open("runUploadSslCertSelfSignedWithPassword"); + + String certFile = getClass().getResource("/certs/rsa_self_signed_with_pwd.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_self_signed_with_pwd.key").getFile(); + String password = "test"; + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + + certService._accountDao = Mockito.mock(AccountDao.class); + when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); + + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + Field passField = _class.getDeclaredField("password"); + passField.setAccessible(true); + passField.set(uploadCmd, password); + + certService.uploadSslCert(uploadCmd); + } + + private void runUploadSslCertSelfSignedNoPassword() throws Exception { + + TransactionLegacy txn = TransactionLegacy.open("runUploadSslCertSelfSignedNoPassword"); + + String certFile = getClass().getResource("/certs/rsa_self_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_self_signed.key").getFile(); + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + + certService._accountDao = Mockito.mock(AccountDao.class); + when(certService._accountDao.findByIdIncludingRemoved(anyLong())).thenReturn((AccountVO)account); + + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + certService.uploadSslCert(uploadCmd); + } + + + private void runUploadSslCertBadChain() throws IOException, IllegalAccessException, NoSuchFieldException { + //To change body of created methods use File | Settings | File Templates. + String certFile = getClass().getResource("/certs/rsa_ca_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_ca_signed.key").getFile(); + String chainFile = getClass().getResource("/certs/rsa_self_signed.crt").getFile(); + String password = "user"; + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + String chain = URLEncoder.encode(readFileToString(new File(chainFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + Field passField = _class.getDeclaredField("password"); + passField.setAccessible(true); + passField.set(uploadCmd, password); + + Field chainField = _class.getDeclaredField("chain"); + chainField.setAccessible(true); + chainField.set(uploadCmd, chain); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Invalid certificate chain")); + } + } + + private void runUploadSslCertNoRootCert() throws IOException, IllegalAccessException, NoSuchFieldException { + + //To change body of created methods use File | Settings | File Templates. + String certFile = getClass().getResource("/certs/rsa_ca_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_ca_signed.key").getFile(); + String chainFile = getClass().getResource("/certs/rsa_ca_signed2.crt").getFile(); + String password = "user"; + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + String chain = URLEncoder.encode(readFileToString(new File(chainFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + Field passField = _class.getDeclaredField("password"); + passField.setAccessible(true); + passField.set(uploadCmd, password); + + Field chainField = _class.getDeclaredField("chain"); + chainField.setAccessible(true); + chainField.set(uploadCmd, chain); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("No root certificates found")); + } + + } + + private void runUploadSslCertNoChain() throws IOException, IllegalAccessException, NoSuchFieldException { + + String certFile = getClass().getResource("/certs/rsa_ca_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_ca_signed.key").getFile(); + String password = "user"; + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + Field passField = _class.getDeclaredField("password"); + passField.setAccessible(true); + passField.set(uploadCmd, password); + + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("No chain given and certificate not self signed")); + } + + } + + private void runUploadSslCertBadPassword() throws IOException, IllegalAccessException, NoSuchFieldException { + + String certFile = getClass().getResource("/certs/rsa_self_signed_with_pwd.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_self_signed_with_pwd.key").getFile(); + String password = "bad_password"; + + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + Field passField = _class.getDeclaredField("password"); + passField.setAccessible(true); + passField.set(uploadCmd, password); + + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("please check password and data")); + } + + } + + private void runUploadSslCertBadkeyPair() throws IOException, IllegalAccessException, NoSuchFieldException { + // Reading appropritate files + String certFile = getClass().getResource("/certs/rsa_self_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_random_pkey.key").getFile(); + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Bad public-private key")); + } + } + + private void runUploadSslCertBadkeyAlgo() throws IOException, IllegalAccessException, NoSuchFieldException { + + // Reading appropritate files + String certFile = getClass().getResource("/certs/rsa_self_signed.crt").getFile(); + String keyFile = getClass().getResource("/certs/dsa_self_signed.key").getFile(); + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Public and private key have different algorithms")); + } + } + + private void runUploadSslCertExpiredCert() throws IOException, IllegalAccessException, NoSuchFieldException { + + // Reading appropritate files + String certFile = getClass().getResource("/certs/expired_cert.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_self_signed.key").getFile(); + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Certificate expired")); + } + } + + private void runUploadSslCertNotX509() throws IOException, IllegalAccessException, NoSuchFieldException { + // Reading appropritate files + String certFile = getClass().getResource("/certs/non_x509_pem.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_self_signed.key").getFile(); + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Expected X509 certificate")); + } + } + + private void runUploadSslCertBadFormat() throws IOException, IllegalAccessException, NoSuchFieldException { + + // Reading appropritate files + String certFile = getClass().getResource("/certs/bad_format_cert.crt").getFile(); + String keyFile = getClass().getResource("/certs/rsa_self_signed.key").getFile(); + + String cert = URLEncoder.encode(readFileToString(new File(certFile)), "UTF-8"); + String key = URLEncoder.encode(readFileToString(new File(keyFile)), "UTF-8"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.persist(any(SslCertVO.class))).thenReturn(new SslCertVO()); + + //creating the command + UploadSslCertCmd uploadCmd = new UploadSslCertCmdExtn(); + Class _class = uploadCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("cert"); + certField.setAccessible(true); + certField.set(uploadCmd, cert); + + Field keyField = _class.getDeclaredField("key"); + keyField.setAccessible(true); + keyField.set(uploadCmd, key); + + try { + certService.uploadSslCert(uploadCmd); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Invalid certificate format")); + } + } + + + @Test + public void testDeleteSslCert() throws Exception { + /* Test1: Delete with an invalid ID should fail */ + runDeleteSslCertInvalidId(); + + /* Test2: Delete with a cert id bound to a lb should fail */ + runDeleteSslCertBoundCert(); + + /* Test3: Delete with a valid Id should succeed */ + runDeleteSslCertValid(); + + + } + + private void runDeleteSslCertValid() throws Exception { + + TransactionLegacy txn = TransactionLegacy.open("runDeleteSslCertValid"); + + CertServiceImpl certService = new CertServiceImpl(); + long certId = 1; + + //setting mock objects + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.remove(anyLong())).thenReturn(true); + when(certService._sslCertDao.findById(anyLong())).thenReturn(new SslCertVO()); + + // a rule holding the cert + + certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); + when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null); + + //creating the command + DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); + Class _class = deleteCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("id"); + certField.setAccessible(true); + certField.set(deleteCmd, certId); + + certService.deleteSslCert(deleteCmd); + } + + private void runDeleteSslCertBoundCert() throws NoSuchFieldException, IllegalAccessException { + + TransactionLegacy txn = TransactionLegacy.open("runDeleteSslCertBoundCert"); + + CertServiceImpl certService = new CertServiceImpl(); + + //setting mock objects + long certId = 1; + + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.remove(anyLong())).thenReturn(true); + when(certService._sslCertDao.findById(anyLong())).thenReturn(new SslCertVO()); + + // rule holding the cert + certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); + + List lbMapList = new ArrayList(); + lbMapList.add(new LoadBalancerCertMapVO()); + + certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); + when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(lbMapList); + + + certService._entityMgr = Mockito.mock(EntityManager.class); + when(certService._entityMgr.findById(eq(LoadBalancerVO.class), anyLong())).thenReturn(new LoadBalancerVO()); + + //creating the command + DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); + Class _class = deleteCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("id"); + certField.setAccessible(true); + certField.set(deleteCmd, certId); + + try { + certService.deleteSslCert(deleteCmd); + }catch (Exception e){ + assertTrue(e.getMessage().contains("Certificate in use by a loadbalancer")); + } + + + } + + private void runDeleteSslCertInvalidId() throws NoSuchFieldException, IllegalAccessException { + + TransactionLegacy txn = TransactionLegacy.open("runDeleteSslCertInvalidId"); + + long certId = 1; + CertServiceImpl certService = new CertServiceImpl(); + + certService._accountMgr = Mockito.mock(AccountManager.class); + Account account = new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(certService._accountMgr.getAccount(anyLong())).thenReturn(account); + + certService._sslCertDao = Mockito.mock(SslCertDao.class); + when(certService._sslCertDao.remove(anyLong())).thenReturn(true); + when(certService._sslCertDao.findById(anyLong())).thenReturn(null); + + // no rule holding the cert + certService._lbCertDao = Mockito.mock(LoadBalancerCertMapDao.class); + when(certService._lbCertDao.listByCertId(anyLong())).thenReturn(null); + + //creating the command + DeleteSslCertCmd deleteCmd = new DeleteSslCertCmdExtn(); + Class _class = deleteCmd.getClass().getSuperclass(); + + Field certField = _class.getDeclaredField("id"); + certField.setAccessible(true); + certField.set(deleteCmd, certId); + + try { + certService.deleteSslCert(deleteCmd); + }catch (Exception e){ + assertTrue(e.getMessage().contains("Invalid certificate id")); + } + + } + + + public class UploadSslCertCmdExtn extends UploadSslCertCmd { + @Override + public long getEntityOwnerId() { + return 1; + } + } + + public class DeleteSslCertCmdExtn extends DeleteSslCertCmd { + @Override + public long getEntityOwnerId() { + return 1; + } + } +} diff --git a/server/test/resources/certs/bad_format_cert.crt b/server/test/resources/certs/bad_format_cert.crt new file mode 100644 index 00000000000..bab377a1720 --- /dev/null +++ b/server/test/resources/certs/bad_format_cert.crt @@ -0,0 +1 @@ +BAD FORMAT CERT diff --git a/server/test/resources/certs/dsa_self_signed.crt b/server/test/resources/certs/dsa_self_signed.crt new file mode 100644 index 00000000000..9ee3dc8e5dc --- /dev/null +++ b/server/test/resources/certs/dsa_self_signed.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEaDCCBBACCQDB6QTHSA74AzAJBgcqhkjOOAQDMEUxCzAJBgNVBAYTAkFVMRMw +EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0 +eSBMdGQwHhcNMTMxMDIxMTUxMzE1WhcNMTQxMDIxMTUxMzE1WjBFMQswCQYDVQQG +EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk +Z2l0cyBQdHkgTHRkMIIDSDCCAjoGByqGSM44BAEwggItAoIBAQD1cLkWeTvzloom +uaHmB0ANyrmHTum6bVVMyN2V/it8BAErugqQBIaNtF2EOmJ3baxsxIROOqJ5uVx0 +pymYVr4BcS3R6H2G7lSWHa5iA/UMfVp9yHroK+WYdN5ZVKGYcUTvKZXtyr2OX3Rc +KJJ2yp4qbcQTB2GlV6eZdpX3l38G/03n/Wi5yjU2/p56R80FAaLtCr4wJoS2aXxU +Iytps+msEn0LRZuFHpW1sLIKPLRCnjFXWeWKdJu6bggUVB0GjfsZR67XzFY5nRvX +7/vW2XS5Vo4X6gSOym0O/8/vzUp1gQSwHiMQQRAoRYoZPxWo8ACMsqdj0MTbN32y +b11//OlXAiEAoR8xDStCDTaQ2Ale9swNzLB8vWFzmSLQXXOM1PY10fMCggEBAO1p +RV1kluxjYCKec12MKdTBqO2QZnOOVFsY2vpIavgqpxyGaHRwY8Cm7BGosV2chMZw +G6xMz5CRnR55KasaX1Vz2xAz7PwczXWDQA59Il5tQbQdewitm1S3NRb1n9u+cNkQ +E6ZekjdW9tRykvaNQHH8EBzgQ9KXCYzJ8nFLk2DMt2Mor/paXfobNzO/vi2UgL+B +5/E8BXoMtBFPhiz72CsCiXp/usROe/UAejow/CTHYC2mfcPhKt2jIVelXx7Baf0n +K1SWKBpNI4ucBj+/4L3Be0ldqDGmeTRUNTNpJIzmAyplUvnpOiqCbzKst57+l4ZE +xdVgv2LiIrTaqTn1L4sDggEGAAKCAQEAv0hyFYj8IMEaOCk9+6wb32NGEGoEz4re +YW1O02Kij2/0YJk0CPyg0ozIpJq9FiHvOzE+2/Eg5jLVTLlAJbjnGjSnzZJ6pJHw +zhwnJ9wT4to51jLvG1v82iL2FfFKOZFjABxC+kND9cAUXu3URIGfdYJl1rBxvOD1 +WZ03Gk90GMCLUIMqqUYBQg7XRNVf0k1AgiRgDWpdLkKOGiDntAj/unXdFrbse2xD +IbqBGhCNtPVx34CZ3bUWrvYBoj+BUinfItRK4rkZTEGJinoxbKDvdqoewgk2nSty +7CH40wFS4ni4DCvYTEwUoUuciQaU4XUOOSYFS9IjNWOR8uGBtORteTAJBgcqhkjO +OAQDA0cAMEQCIHqfrNbyMadxZ3uCPr8QPj+17XZZod8B7F8VgZW3R5vSAiAV/WMF +vQ1Dwpr4wJOjNELDe5AEH9WGvevfuc54vmdAdg== +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/dsa_self_signed.key b/server/test/resources/certs/dsa_self_signed.key new file mode 100644 index 00000000000..9a9d6675d5d --- /dev/null +++ b/server/test/resources/certs/dsa_self_signed.key @@ -0,0 +1,20 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIDVwIBAAKCAQEA9XC5Fnk785aKJrmh5gdADcq5h07pum1VTMjdlf4rfAQBK7oK +kASGjbRdhDpid22sbMSETjqieblcdKcpmFa+AXEt0eh9hu5Ulh2uYgP1DH1afch6 +6CvlmHTeWVShmHFE7ymV7cq9jl90XCiSdsqeKm3EEwdhpVenmXaV95d/Bv9N5/1o +uco1Nv6eekfNBQGi7Qq+MCaEtml8VCMrabPprBJ9C0WbhR6VtbCyCjy0Qp4xV1nl +inSbum4IFFQdBo37GUeu18xWOZ0b1+/71tl0uVaOF+oEjsptDv/P781KdYEEsB4j +EEEQKEWKGT8VqPAAjLKnY9DE2zd9sm9df/zpVwIhAKEfMQ0rQg02kNgJXvbMDcyw +fL1hc5ki0F1zjNT2NdHzAoIBAQDtaUVdZJbsY2AinnNdjCnUwajtkGZzjlRbGNr6 +SGr4Kqcchmh0cGPApuwRqLFdnITGcBusTM+QkZ0eeSmrGl9Vc9sQM+z8HM11g0AO +fSJebUG0HXsIrZtUtzUW9Z/bvnDZEBOmXpI3VvbUcpL2jUBx/BAc4EPSlwmMyfJx +S5NgzLdjKK/6Wl36Gzczv74tlIC/gefxPAV6DLQRT4Ys+9grAol6f7rETnv1AHo6 +MPwkx2Atpn3D4SrdoyFXpV8ewWn9JytUligaTSOLnAY/v+C9wXtJXagxpnk0VDUz +aSSM5gMqZVL56Toqgm8yrLee/peGRMXVYL9i4iK02qk59S+LAoIBAQC/SHIViPwg +wRo4KT37rBvfY0YQagTPit5hbU7TYqKPb/RgmTQI/KDSjMikmr0WIe87MT7b8SDm +MtVMuUAluOcaNKfNknqkkfDOHCcn3BPi2jnWMu8bW/zaIvYV8Uo5kWMAHEL6Q0P1 +wBRe7dREgZ91gmXWsHG84PVZnTcaT3QYwItQgyqpRgFCDtdE1V/STUCCJGANal0u +Qo4aIOe0CP+6dd0Wtux7bEMhuoEaEI209XHfgJndtRau9gGiP4FSKd8i1EriuRlM +QYmKejFsoO92qh7CCTadK3LsIfjTAVLieLgMK9hMTBShS5yJBpThdQ45JgVL0iM1 +Y5Hy4YG05G15AiBO/b8wvyKsJJAInNbsLH7OPitH3qKsI18IxykJSl9lTw== +-----END DSA PRIVATE KEY----- diff --git a/server/test/resources/certs/expired_cert.crt b/server/test/resources/certs/expired_cert.crt new file mode 100644 index 00000000000..d133f24bb74 --- /dev/null +++ b/server/test/resources/certs/expired_cert.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDVzCCAj+gAwIBAgIJAJRInPvOqxbXMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNV +BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg +Q29tcGFueSBMdGQwHhcNMTMxMDIxMjAwNjA5WhcNMTMxMDIwMjAwNjA5WjBCMQsw +CQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh +dWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +3rASFvBmAF+CHn58TU5ib0HuMD4gxutohjzQjJXYRFs1cmiLb9esO0Cvk0DFaQuq +lpxw4Dhe6kxRbNQKkPFr0zsv9B8I/o8UQmclnZ0I++ixlAq4VyP6H0sewrmdVbrV +mSH0eG1t0hLqXUmxX/XX1kkbHOgZQQk90Sew23VwTVxbywq8yjkYLa2hlBXh33rX +siky7JFiF0TJE2r6wNB60BQMdi2EErtBUPL/1LD7+VuB/Y6xZpwivKwMIXeFdzSr +I2gGCn+zf01kNfHj0YrA2bH0i5FX4/9YSpd8PFIOYc/gA+3MNO0xMWchbz6AfjPQ +aR4tGLsRBjjwvLIZwHzyWQIDAQABo1AwTjAdBgNVHQ4EFgQUo/kIdWN+yxvnWUoK +/ZJYNl2wY9cwHwYDVR0jBBgwFoAUo/kIdWN+yxvnWUoK/ZJYNl2wY9cwDAYDVR0T +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAJ/LwjkhXQFOcfUmAoIeBIDAMayy7 +HEJusMOA+uUPPuEemgU7DTbwABCaavfBza7QvG171LsTGtvgnvwDg7rdScUOcoX8 +w0XZbhr+dZzvashVmMz4oY6hGw29eGo7M01Rm4msX7bW1IXmdWmDcqcNT6/dKOgj +tjMR2JvN9I4qwZ41xXAeUHDUqKjgsKlhflBbOX7K07tbpHFMQZcoOs19Jqve8Gfm +MbH0hZw3LC2YNed8ne/3/lXKNZIhbyZp1IJ/rjgruEZ0ObOwqB1IGR0UjQbAw102 +1D4L8FOzmDi4LfhKPgGc/BMeuPRozxQi60TzrnXN5eQSb0ukFvScMhAIrQ== +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/non_x509_pem.crt b/server/test/resources/certs/non_x509_pem.crt new file mode 100644 index 00000000000..fbbae8ed75f --- /dev/null +++ b/server/test/resources/certs/non_x509_pem.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICtzCCAZ8CAQAwcjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwEU3ll +ZDEcMBoGCSqGSIb3DQEJARYNc3llZEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKmQeRXpkeGRhzdj3aJiWUcZtKdcjPCdtphx8gHk1GV1 +vHK2zYenwe23EbSsfkOAQx2p86jCpghN7b+ECilmou4C7ASPS2U8n+GhWdl4eUK4 +Gmz7+daRqcDQOCTCJWSybtShYzvfp2SaEt/TcUgDT+k6xRitqcIkAY7boGY1Cehy +O6hYdlFkg0oU1XCA0usIaSEi7gOTijpGe2jSh7CTBRRWiClQnqE8VT7x4hXQEDF6 +u26K/ptAL90bgyFUuX2dEH5dKd/5QAyAfdrLV6a3wIvikCUGZy23Twtxot4kFVYf +S2x3H9BS6j/mIvrUj95CLi2Eu6t4z5uHMOrf8k0NjN8CAwEAAaAAMA0GCSqGSIb3 +DQEBBQUAA4IBAQBa5B6xzAkx3OtJEgOkTJ0nID2TsTt6eQBrp+//jhT/9yKLHmd5 +SeNcLzMWDlTQ+zNlLf9+lreO+CmlolaOKDRXh9eXbyNq0/I2QxOEsIlXqH4dVoCB +6UkV8eA0lFeNdFJaCla5/QTKmv4f0eUakbI5Scd1PlBr+YOplvI9fpLaxHGmVzCX +s3WQ7m7SN5hZav7dO8krheZL7N3AYZoCY0QbQ3JTeoakLenmFXqvsckP6in5NQJh +ECaJprYxrxR+5GPjpUkxu7YGLloXHvnnINeZGJG0TB7kPDO+axDxloiI2eYlT/mp +HxdgL9BvDYNfI+0NcZYHguz8GWuWiTZC7F26 +-----END CERTIFICATE REQUEST----- diff --git a/server/test/resources/certs/root_chain.crt b/server/test/resources/certs/root_chain.crt new file mode 100644 index 00000000000..2ed80858532 --- /dev/null +++ b/server/test/resources/certs/root_chain.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDnTCCAoWgAwIBAgIJALXV1B5/vewgMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNV +BAYTAkFVMQ0wCwYDVQQIDARTb21lMQwwCgYDVQQKDANPcmcxDDAKBgNVBAsMA0Rl +djENMAsGA1UEAwwETmFtZTEcMBoGCSqGSIb3DQEJARYNdGVzdEBtYWlsLmNvbTAe +Fw0xMzEwMjExNjAxMDdaFw0xNjEwMjAxNjAxMDdaMGUxCzAJBgNVBAYTAkFVMQ0w +CwYDVQQIDARTb21lMQwwCgYDVQQKDANPcmcxDDAKBgNVBAsMA0RldjENMAsGA1UE +AwwETmFtZTEcMBoGCSqGSIb3DQEJARYNdGVzdEBtYWlsLmNvbTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALQZLQa2R64GRCuoh59VFvKoXnAM+4H4sW9E +jiURT/CeH6rbD0IbEMZZ3o84VfQw1zDsVXN/GXq3IEMp8uBBpWJuZRBF1UeDMYlB +bouMqUGL05Ov51zK2aQK/83S8MoQI7KV1FGJNti4iwUzemG1fClrBqjCFJQKmv8y +0z1UaeniAR7ygedIB4I2Y4a/DxtI0e2EsS0TcViwKHGrLArO0GfvNbH+tXqTaotF +X5eyinUFqQxT3JvnlIIernk0ly8c07mqOFbFqHrhFXxddD4pZrUetHXM2MKLdCMu +fvXsmMXSAgQ5F97GWmiDEJ9zMDxGoSmhTIN96FwPCRDr7e22lEsCAwEAAaNQME4w +HQYDVR0OBBYEFIxSziB7ssNqFvhV2MSf1GYvGHQYMB8GA1UdIwQYMBaAFIxSziB7 +ssNqFvhV2MSf1GYvGHQYMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AB1rcxZL6xGuk8PSoBQ0imREcVf9BcEvGIC6uubPSXuoJ/gr584vo3pRJpTpHQyK +xUUwG6gCaDgAMYX177GBamGCt056ThSLKFROIPVrigZ5yY1NWznNq3zjWS4jIHkV +vGd+Gx8t3qYBhsn+v6Y6gRTjMOVQum+rvxvixG7n97DaxBnrwNWXbzZQ9spHrQsT +dsSF/kf9NKkWM0zKh+f/FSNmveJKKvZ+WQZC/MKUfc5VHjyLldXhrffcxzek/dOc +8YADSICSizvXCP/QjyVVl8dpKr/3c00r16Ei3QQaFhHES0bv/sKLnTwQwKDfJthu +bQj7M/XGWi33JQgoMHktYhI= +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/rsa_ca_signed.crt b/server/test/resources/certs/rsa_ca_signed.crt new file mode 100644 index 00000000000..fb74f17574b --- /dev/null +++ b/server/test/resources/certs/rsa_ca_signed.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID1TCCAr2gAwIBAgIJALXV1B5/vewhMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNV +BAYTAkFVMQ0wCwYDVQQIDARTb21lMQwwCgYDVQQKDANPcmcxDDAKBgNVBAsMA0Rl +djENMAsGA1UEAwwETmFtZTEcMBoGCSqGSIb3DQEJARYNdGVzdEBtYWlsLmNvbTAe +Fw0xMzEwMjExNjE4MjJaFw0xNDEwMjExNjE4MjJaMHIxCzAJBgNVBAYTAkFVMRMw +EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0 +eSBMdGQxDTALBgNVBAMMBFN5ZWQxHDAaBgkqhkiG9w0BCQEWDXN5ZWRAdGVzdC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpkHkV6ZHhkYc3Y92i +YllHGbSnXIzwnbaYcfIB5NRldbxyts2Hp8HttxG0rH5DgEMdqfOowqYITe2/hAop +ZqLuAuwEj0tlPJ/hoVnZeHlCuBps+/nWkanA0DgkwiVksm7UoWM736dkmhLf03FI +A0/pOsUYranCJAGO26BmNQnocjuoWHZRZINKFNVwgNLrCGkhIu4Dk4o6Rnto0oew +kwUUVogpUJ6hPFU+8eIV0BAxertuiv6bQC/dG4MhVLl9nRB+XSnf+UAMgH3ay1em +t8CL4pAlBmctt08LcaLeJBVWH0tsdx/QUuo/5iL61I/eQi4thLureM+bhzDq3/JN +DYzfAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wg +R2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBR2LIRfVveDgQB3dC7TOYhX +BEv71DAfBgNVHSMEGDAWgBSMUs4ge7LDahb4VdjEn9RmLxh0GDANBgkqhkiG9w0B +AQUFAAOCAQEAPjN/sdLcPfMh5ep29vp/7JTh6dUYnBNATYaXxx8j2XdnMCKeRfgP +WOJur8HDPSayWWKKlztiQbJV5jDS5vyuMWI1a5/KIAQlOJep+anpR1QnQaX4/M4Z +YUJo1fPs6tg47dXRpZZaJ+Hqwh0ZftCQoUq/sBxawXf6sbxsjoUmzxQLBqzYo1LJ +jwxBs6C9aM8LDHFz4TVlyclSFQXiLMosj1jLBQ+TqzCxS6qOfJeMM9STXI9W3F2k +duXeceqOwEkh8aeSUIztYFpX34d4SA4DDX5GUEaOeOR/abnXjH52vE6tM/m7NOve +5+I/BrlT3heRqiD6Z2ofSsFhG86YeF9Q3w== +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/rsa_ca_signed.key b/server/test/resources/certs/rsa_ca_signed.key new file mode 100644 index 00000000000..d30dd8e8e99 --- /dev/null +++ b/server/test/resources/certs/rsa_ca_signed.key @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIN4x8YHLIb60CAggA +MBQGCCqGSIb3DQMHBAiuWe+C2SitUgSCBMhVxMKivNaQh9SQedh2GQ8vlhI2/mKf +r6zVUgODOdmFRj/PAlQu6B+VH8u2Ef5tr74O9UyZUQpC6oI0npvQOGqnhIxECR8D +zepFlC0s+6kNRqfzXiMhGTsfbs3xUE1TZK1z5556OS4GlihIB0E5F7GdlulHELeA +dnEItqDffWPQczTmSmFqtH7G/ksGQhSA2reBIDNgxWreBh9x9h2TftEvhhogdkr2 +XQpzxcby2v2z6Hut1lfVkLQNdvdHYdDG751NQltOmGvncXkTNJ+tSByXuY9ITtYz +XqwY/vAEX+YYjCrWcvMmhU1t6B9cZ3viFzIIIltqtvDo3rybicpM3xvmnYnTF35j +sGebcynzZedrLUHwD6/o0jBzFJN26QBxDGrlmn9E8HBhmjMCeSyZTXtSkwN0dAhu +EHT2NgdC/4G4+JHsb3Oetl6AbUyYs2eWTRgr6bgBezbiDqKMj1QtGECkPQE9tFFP +Jtma6lGJ1/u8zLFYNjigKZgXaNbtlMpslk+KDTGaTSbbVEaaxWSc0YlHz329ovQC +1btrTE71FoNjRsTRaDRXC7BfrrMtnLhG2SmROKzyBtoxFymfEmASpdGERO+c2712 +Z0NLpHJL5ocsRr/onVi0auFC/nuaq6QqYF5OPtZhYh3+IDd193LP3xo8hnFjTq90 +9zV1QI2uHfTfijI4OABYSSZLxrl2IFF7Z/e4XkWSXrneR2Ne5GoYX7w6wshiuubQ +bDPUHODsy7uQJ3ZEmmmd5xWvA3h3F5Yyls3WEuz8+jYR4iPKdjt8DJuz9j+7IP3C +LoRa3KhxIPAzziQw+tMFVCozLLfS1kN8mg5SwU9Dp4HUPY/n3KnjVSjUJ347KAgW ++ykPlz4S1H0A2GyGWhdyX3J839UOdXfCsfKQQ1FLOBvhQgBNGzoRIgDrsZdrxgWa +XtF+Ct2/2/O+503I6X90maXzhshmGw/NKsiNx7YOdUiu6w3N4LajIWE689UUU7Dr +EtM8HcfmBnE/cZTbeWbQBfl1GqigMp+YOAY2sw0rZdF4ocmnqoCWLVN2j8O/re5g +20y5eHkztPOZ+NNczo5PP96ng1XEMVzs/h6xDHzsak6osZb5b+Hs9kcYuqBEqr16 +3DVwaZ45dGwNN90Q9YmrgEdCqtCAU12w/YYVB/aB701Ijg0NhVsh7PgWaJIOJD56 +YTaiWIzQaZ/uM0KlgLz2eI9VXcuv24gUMAUMaI84mInnIrax1zFMrlCjEcR8Zxvk +jCCY6Uq9WH30cUo7cMHWLWMzsl7PC7xpYSHPClqzCUluUgQwqoOs5Ux4nYl+JI7C +ZfJ8BUMCD2RJtjvJhkE6LEkcrCjwnvappRaXbN54IVXpuMl2XYtp44T117QulEj1 +I/jk1mrpkXRKi9ZsKsjDH9VMy1hcKHn4CgTxmtRYN6LPA4tamxzVLxIi6YDU0142 +l1u763cT7cH14lvzUvEQMFbk/s0AUl8zeZAwjDayNlD/ljz7nZnJ3NToMlxeoK0a +F6c/RgQBwxR8NMdo19Irv8stxo9WGB2/0Q8WCxW7ENHlBpvX5zXKRJMswFKp0ft6 +dT7hOBPgJlD7C1eX5jVcSz6kDRM6gQ7K/c5QcJa6qNAC2Jw6yBBYltqiRalFWX46 +VcM= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/server/test/resources/certs/rsa_ca_signed2.crt b/server/test/resources/certs/rsa_ca_signed2.crt new file mode 100644 index 00000000000..fb74f17574b --- /dev/null +++ b/server/test/resources/certs/rsa_ca_signed2.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID1TCCAr2gAwIBAgIJALXV1B5/vewhMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNV +BAYTAkFVMQ0wCwYDVQQIDARTb21lMQwwCgYDVQQKDANPcmcxDDAKBgNVBAsMA0Rl +djENMAsGA1UEAwwETmFtZTEcMBoGCSqGSIb3DQEJARYNdGVzdEBtYWlsLmNvbTAe +Fw0xMzEwMjExNjE4MjJaFw0xNDEwMjExNjE4MjJaMHIxCzAJBgNVBAYTAkFVMRMw +EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0 +eSBMdGQxDTALBgNVBAMMBFN5ZWQxHDAaBgkqhkiG9w0BCQEWDXN5ZWRAdGVzdC5j +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpkHkV6ZHhkYc3Y92i +YllHGbSnXIzwnbaYcfIB5NRldbxyts2Hp8HttxG0rH5DgEMdqfOowqYITe2/hAop +ZqLuAuwEj0tlPJ/hoVnZeHlCuBps+/nWkanA0DgkwiVksm7UoWM736dkmhLf03FI +A0/pOsUYranCJAGO26BmNQnocjuoWHZRZINKFNVwgNLrCGkhIu4Dk4o6Rnto0oew +kwUUVogpUJ6hPFU+8eIV0BAxertuiv6bQC/dG4MhVLl9nRB+XSnf+UAMgH3ay1em +t8CL4pAlBmctt08LcaLeJBVWH0tsdx/QUuo/5iL61I/eQi4thLureM+bhzDq3/JN +DYzfAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wg +R2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBR2LIRfVveDgQB3dC7TOYhX +BEv71DAfBgNVHSMEGDAWgBSMUs4ge7LDahb4VdjEn9RmLxh0GDANBgkqhkiG9w0B +AQUFAAOCAQEAPjN/sdLcPfMh5ep29vp/7JTh6dUYnBNATYaXxx8j2XdnMCKeRfgP +WOJur8HDPSayWWKKlztiQbJV5jDS5vyuMWI1a5/KIAQlOJep+anpR1QnQaX4/M4Z +YUJo1fPs6tg47dXRpZZaJ+Hqwh0ZftCQoUq/sBxawXf6sbxsjoUmzxQLBqzYo1LJ +jwxBs6C9aM8LDHFz4TVlyclSFQXiLMosj1jLBQ+TqzCxS6qOfJeMM9STXI9W3F2k +duXeceqOwEkh8aeSUIztYFpX34d4SA4DDX5GUEaOeOR/abnXjH52vE6tM/m7NOve +5+I/BrlT3heRqiD6Z2ofSsFhG86YeF9Q3w== +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/rsa_ca_signed2.key b/server/test/resources/certs/rsa_ca_signed2.key new file mode 100644 index 00000000000..d30dd8e8e99 --- /dev/null +++ b/server/test/resources/certs/rsa_ca_signed2.key @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIN4x8YHLIb60CAggA +MBQGCCqGSIb3DQMHBAiuWe+C2SitUgSCBMhVxMKivNaQh9SQedh2GQ8vlhI2/mKf +r6zVUgODOdmFRj/PAlQu6B+VH8u2Ef5tr74O9UyZUQpC6oI0npvQOGqnhIxECR8D +zepFlC0s+6kNRqfzXiMhGTsfbs3xUE1TZK1z5556OS4GlihIB0E5F7GdlulHELeA +dnEItqDffWPQczTmSmFqtH7G/ksGQhSA2reBIDNgxWreBh9x9h2TftEvhhogdkr2 +XQpzxcby2v2z6Hut1lfVkLQNdvdHYdDG751NQltOmGvncXkTNJ+tSByXuY9ITtYz +XqwY/vAEX+YYjCrWcvMmhU1t6B9cZ3viFzIIIltqtvDo3rybicpM3xvmnYnTF35j +sGebcynzZedrLUHwD6/o0jBzFJN26QBxDGrlmn9E8HBhmjMCeSyZTXtSkwN0dAhu +EHT2NgdC/4G4+JHsb3Oetl6AbUyYs2eWTRgr6bgBezbiDqKMj1QtGECkPQE9tFFP +Jtma6lGJ1/u8zLFYNjigKZgXaNbtlMpslk+KDTGaTSbbVEaaxWSc0YlHz329ovQC +1btrTE71FoNjRsTRaDRXC7BfrrMtnLhG2SmROKzyBtoxFymfEmASpdGERO+c2712 +Z0NLpHJL5ocsRr/onVi0auFC/nuaq6QqYF5OPtZhYh3+IDd193LP3xo8hnFjTq90 +9zV1QI2uHfTfijI4OABYSSZLxrl2IFF7Z/e4XkWSXrneR2Ne5GoYX7w6wshiuubQ +bDPUHODsy7uQJ3ZEmmmd5xWvA3h3F5Yyls3WEuz8+jYR4iPKdjt8DJuz9j+7IP3C +LoRa3KhxIPAzziQw+tMFVCozLLfS1kN8mg5SwU9Dp4HUPY/n3KnjVSjUJ347KAgW ++ykPlz4S1H0A2GyGWhdyX3J839UOdXfCsfKQQ1FLOBvhQgBNGzoRIgDrsZdrxgWa +XtF+Ct2/2/O+503I6X90maXzhshmGw/NKsiNx7YOdUiu6w3N4LajIWE689UUU7Dr +EtM8HcfmBnE/cZTbeWbQBfl1GqigMp+YOAY2sw0rZdF4ocmnqoCWLVN2j8O/re5g +20y5eHkztPOZ+NNczo5PP96ng1XEMVzs/h6xDHzsak6osZb5b+Hs9kcYuqBEqr16 +3DVwaZ45dGwNN90Q9YmrgEdCqtCAU12w/YYVB/aB701Ijg0NhVsh7PgWaJIOJD56 +YTaiWIzQaZ/uM0KlgLz2eI9VXcuv24gUMAUMaI84mInnIrax1zFMrlCjEcR8Zxvk +jCCY6Uq9WH30cUo7cMHWLWMzsl7PC7xpYSHPClqzCUluUgQwqoOs5Ux4nYl+JI7C +ZfJ8BUMCD2RJtjvJhkE6LEkcrCjwnvappRaXbN54IVXpuMl2XYtp44T117QulEj1 +I/jk1mrpkXRKi9ZsKsjDH9VMy1hcKHn4CgTxmtRYN6LPA4tamxzVLxIi6YDU0142 +l1u763cT7cH14lvzUvEQMFbk/s0AUl8zeZAwjDayNlD/ljz7nZnJ3NToMlxeoK0a +F6c/RgQBwxR8NMdo19Irv8stxo9WGB2/0Q8WCxW7ENHlBpvX5zXKRJMswFKp0ft6 +dT7hOBPgJlD7C1eX5jVcSz6kDRM6gQ7K/c5QcJa6qNAC2Jw6yBBYltqiRalFWX46 +VcM= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/server/test/resources/certs/rsa_random_pkey.key b/server/test/resources/certs/rsa_random_pkey.key new file mode 100644 index 00000000000..8c29b3e20de --- /dev/null +++ b/server/test/resources/certs/rsa_random_pkey.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQD2ZYOSvqPjro7k +JKWggB0FJL45mz3pfvBR0NcHTGgHKdh5hml1GiHHPanYnWqRuKFI7UPWLq3xllvJ +jolMjX6FGzPFuh4wHQ3gHMFlmpi6o1gUkk5QxAeCWmsA77qJAAiLVbm27sqfpvSG +ec6KJOcePDDN/6Jp363Gf8JuSssafg6fAbfwLp7Cm1cxFM3RKN13fUdy50+OcXv7 +uvUlzHZ2ZIVK7FnlFoXOfhFHoyfdZL2Qm8xV3SuUllNPGl7aCM59Y6xR743Rq01j +3E6hHNZ82GlJGaOL413oVsp5J9ZmKV+WM7plFIn86p2JGMoA2xjtON+X6BZdz3YT +ymp7ic+7AgMBAAECggEBAKvkNd3x0TPNWzIdvs4xkg08jNhzTMXQIKdzIg+dZhVZ +RAPDmV5wVJBCnHLZnrb6LspJe8G33vFjC7WZEn+tVk5Vo9CU/uph2oQ2i1TufQ33 +VkNDrg76MqLloTCODXv14gASVfUgsYqfVodaApStGe8l3oZXiF6EBR8tkd6PnxFi +8TPAalFS/0mfjj/dA9zHXoZ0iyl+h6had6kqJNNbP8zgD+TbnfJZVkURNB0cyGVI +8/8d/eO05oQ1DpuvTJ+Q5i8wTDjikUzc4btt6coA/ho4QuOvfsZGsgCzCYsUn0+W +GA+Vn2PVEFV5hJ+MZ9gGmQ5ouC/IVAYkBBC7HlNX70ECgYEA+3DC6rTvXqdrjZz1 +TFWcITfAt7WzfGlHi2LBZ/JNmyIetXmF/sHpqGKkvp7iHDMJ4NeEBXSN9tbbEfhc +1yU+HXYlKkeaZAGaNiCSvqlr/Bouy7dX3jG8xgPGQ1o2gyluaoTEwORf2LgmApYA +q/eQyWTKHLxatTnjlqLULerxqv8CgYEA+t1Wa00XHHgB1D4was59qnpPemIUxpvm +4e3wjyQs6P2kH0F0rKyytQaSXKhkBYRcmh0EnyNSGu7wxM5l3aDTzCDgBHmb1i9P +UXLzWUYnsSgUpUB8jL6YDlUmQ1AMMDqvLagLlOLqPkRmNjN1P4/+6mdoxD5SL0rv +5FeRaOAGR0UCgYEAjWEgGDzYg058CUqCGwPgIEVrFWETpRbFZbiHq1zxChOrVLsZ +/t8l9MpSe+R2mwiPu18zGqYo1OyGjZorCcYlIQe3agiM5UKJZXn3SUGWOFC4k09q +FsO8s1KX/nMRR7raHQa+Yv+GbSNOLBIQGqG/RZ5ojrPSBSihsaeoypDahh0CgYEA ++OK3ZmVpVHlLd0LrzktnKceHKqg8bH8oJWZnj9wYIl/igI/0LYx5EFigxQTblw2m +wc+gUjI8tzPv85HCRovVFWRYXJg6H9l4HBqrjBqqLnzRXtIHv6soOLAJ8iZssTzH +p8hdFS27sGMz9PpAjPtTsUM/EdOyvfDe5/Bo91+rWvECgYEAxgvptntWbXc8QI9n +DFYGigeza0sQTmFtSsob5cux9dtPORChdb6EPNTgOPOfKD4QMkmar/VWedeXOHb9 +Cy1Qz7bgOhIUSMdXzw4hPOmLrT7IbhG5CHawwHanGycrQ/bJcV00lsv0BEj3N/NJ +PW/vxADWc9H3AcVeMi5So6gTBt4= +-----END PRIVATE KEY----- diff --git a/server/test/resources/certs/rsa_self_signed.crt b/server/test/resources/certs/rsa_self_signed.crt new file mode 100644 index 00000000000..710326ef8e5 --- /dev/null +++ b/server/test/resources/certs/rsa_self_signed.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBjCCAe4CCQCEkqahWR0hjjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTEzMTAyMTEzNTIyMFoXDTE0MTAyMTEzNTIyMFowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN6wEhbwZgBfgh5+fE1OYm9B7jA+IMbraIY80IyV2ERbNXJoi2/XrDtAr5NAxWkL +qpaccOA4XupMUWzUCpDxa9M7L/QfCP6PFEJnJZ2dCPvosZQKuFcj+h9LHsK5nVW6 +1Zkh9HhtbdIS6l1JsV/119ZJGxzoGUEJPdEnsNt1cE1cW8sKvMo5GC2toZQV4d96 +17IpMuyRYhdEyRNq+sDQetAUDHYthBK7QVDy/9Sw+/lbgf2OsWacIrysDCF3hXc0 +qyNoBgp/s39NZDXx49GKwNmx9IuRV+P/WEqXfDxSDmHP4APtzDTtMTFnIW8+gH4z +0GkeLRi7EQY48LyyGcB88lkCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAlgx04bvU +/EE5z7lJsYmUM2oi8FjqZcZkD4F1ku7zvdAXaDNhOHjrR5LxGL+iI/N9S8lKVeSV +xZv+EXAT0NqkTidNFjvP7coctDrrM+JHSNTRlr2GnnYjCnjEph4+ZXNppx8vnhXe +7jDnHoXL/C5GIPOm0+LQaH1AlGTPF0lnBrtQaz1UG34vCr8SSUtRbTDDxH/liXfc +hfvVnf4OV5Duj0oUXsmB3YzITYZnZ/xvZ4Dw6rOU/U5Vetng+msOOt8momeTCnWB +/d1clA7rulJTCNZXb0YyaUNaC6eQX7S9JHnluB67b9yp4yg8f00qz4xR165eTQmq +mLiuE/U5fTODvA== +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/rsa_self_signed.key b/server/test/resources/certs/rsa_self_signed.key new file mode 100644 index 00000000000..14b95e6ea1f --- /dev/null +++ b/server/test/resources/certs/rsa_self_signed.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA3rASFvBmAF+CHn58TU5ib0HuMD4gxutohjzQjJXYRFs1cmiL +b9esO0Cvk0DFaQuqlpxw4Dhe6kxRbNQKkPFr0zsv9B8I/o8UQmclnZ0I++ixlAq4 +VyP6H0sewrmdVbrVmSH0eG1t0hLqXUmxX/XX1kkbHOgZQQk90Sew23VwTVxbywq8 +yjkYLa2hlBXh33rXsiky7JFiF0TJE2r6wNB60BQMdi2EErtBUPL/1LD7+VuB/Y6x +ZpwivKwMIXeFdzSrI2gGCn+zf01kNfHj0YrA2bH0i5FX4/9YSpd8PFIOYc/gA+3M +NO0xMWchbz6AfjPQaR4tGLsRBjjwvLIZwHzyWQIDAQABAoIBAFBYus4oAsWTsEEM +ZhEGfSGjaith3zWmblowyxZOYm+XcRtMeTLrYCso1bCNqCyUlwIsg9WCwUxMKPzZ +LM7LLJpUOqMcJ4ShXy/uQ3Yw2LL7bEb77zMRugdcdUbQ7eGmvba4t5pT8VHgnUr3 +cdYrv6qDShMN8z6x9OnoJjmoj9J5Ggda6DhsXsvl5Ox85XMOJKd9yyaUfa/qy8b6 +wIyixGQ/9l/GwGONgtrF7yKW3YUE+uhoEp4pqgKsGUIke3l7aWug6dCDjKDMdbX5 +jwSSiw2ilTpQJhi1r8JIMOfMea3addf39VySK7e6cSWhsf1VTVwneJbka13xS6uR +SSdvs7kCgYEA9ynOXh/1+VkpCHJBAPWEIUtPn16KGJB6YEsEf7cfaAQfzQCwJ8E4 +I7/WsHveHXs80HLS/ZJQlIXXsdeMiWdu1rnsQiVBZMmSNOpOD8iP/6mv8eqeeNr+ +3e3JG+j+l3w+/RzX516WC5JPMIsNSIzSlyx8Yht4IYA2uvpJcLdMW2MCgYEA5qY/ +xht6UlbLevGzFFFnM5R9LWSs+Ip88HCBmEwbow7FQTc0TXYbOKxGtPqn88dM91XT +NMpPaGenuioRz+P1sbEFOP/iE4Hyob8643NMkAiwwoxzSf2Bsj+ebJ/U7oC0xKYx +yjLeFWINhDy+I3LDLEXTTfv5GNrFlitqBEA+ThMCgYEAmOrJnhyCD4JlS698nj5I +QF0a5wwTvnzs6dSf9PB0QuOCVVBerEn0FNIk3s3UL0NG7eSMu4uhxTJFr+cfMQfI +YJtpG8d2/QdlKM3p/APna5Mtoyu4XieH1gC/E0CE+25IfksxHRm9FW2xBuSRFFjk +FdnVHtHF8lwkAGzHsTAG0ucCgYEAigFdVT7psMyoEZb+7KBMXKtzPq7nZAsQ+JiI +okSfoK/czMmoLNUHMqC56d20koNkhPVAW2zVmIW08QntAHPIdZqSomlQrxVoxOjz +5lX9sIzSnoWFEfdyG+I++4Wi1VYDU0qRrgdDpI23wrDJn9Ix/5KD/TxP7lQwN0sg +swxxeysCgYBBXGBBJR7+AbreFpOHitw0h32Qdmy6zHTEF8e0SjmEgDv3uwGDdsYO +QQ7g9QPPPUsYtl0+mUmCwDrw1sJeVFtp86AQlQMV89pR2yXZLf0xwT7IN6RAH5Bi +WlV2/pmiMuWB1qSUKgdPzVEd6aqtjD0TIjtryDBHp76YHJR6SzdCCA== +-----END RSA PRIVATE KEY----- diff --git a/server/test/resources/certs/rsa_self_signed_with_pwd.crt b/server/test/resources/certs/rsa_self_signed_with_pwd.crt new file mode 100644 index 00000000000..de5e5c9ac0b --- /dev/null +++ b/server/test/resources/certs/rsa_self_signed_with_pwd.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBjCCAe4CCQD5Q6qF5dVV0jANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTEzMTAyMTEzNTgwNFoXDTE0MTAyMTEzNTgwNFowRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN/7lJtiEs68IC1ZPxY9NA34z9T4AU4LPS/kbQtuxx4X72XOBy+y0cB/qdMD7JNV +h8Mq4URDljhSDyVPdH/+jQr+7kWx2gNe2R/DCnd/meVwwU30JJvpGVZXt+MTef5N +QAbSfDMsuT4FaUY80InbDd24HelrjwunPdY9wwKXO6zL2fLjyDRediiydxcx18Vb +Dq1cm7DRi4mNkmA3RwBQMhxGp3VsfXJ4Hy2WTRCCCxWHZphAh3EUJGK3idum6/7j +HbAwpM/t1kNWN8PZiYDZ1HbccgjmqB7Cub10BfB9g1RByiQ/C87o5cKtQha3uuXR +iBcHISoDydQrgxKgUpiqEF0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEASvulIaVb +zh8z2TysE6RFoYTAYIRXghFrmqCUyyQmUVTvs6vN8iaSXr+WMQJcpgXewWcFrDhr +mIcyRCvF91ZYb7q6lMZFSpE6u/SUGIEtxGUDAfbkbQdKYmrMcbggUUIvSzgUFisO +Kr0H9PEO4AWtCCrtOJFc7jgu03Sv06wDxn9ghkyiBRnVkbAhoKfKnI179yKruJWR +A3ieEj0eFoUbeSH8hDkToj4ynpkAvEGoHjHG9j+8FJxy/PTjkyVPl1ykTs+2Jc1B +Snx8f2afdTenPWyyBm3wFuRZjEAJJLUO0kxM7E8hAwhGsr+XYanwcr1oA1dz6M3f +cq26lpjTH5ITwQ== +-----END CERTIFICATE----- diff --git a/server/test/resources/certs/rsa_self_signed_with_pwd.key b/server/test/resources/certs/rsa_self_signed_with_pwd.key new file mode 100644 index 00000000000..d645a716632 --- /dev/null +++ b/server/test/resources/certs/rsa_self_signed_with_pwd.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,CCA6E4CB4C4039DD + +TaVCJtB0dE9xTZbX7GOaGJwwGHVAMjU1GbRIHf0jODdP+quZvbjklNqsw8Ozlia9 +q/G+UqtRJGlIPPLpce0YCrTo0P3eixZdMs0+hioAEJ4OLtL0SAC6b8q/gB6HRfAx +BvNg+umTqeF9YB68Tcuv/2g4VGKiaePQACyOzMdf7lGY7ojxoJCYZa1mfKb7jWrg +FLwmTtLLhNjb6CnOKo3klIef3A6zdutpgxF1gARzdRyXg4qCA3boYnwEptTOlJFu +ovxbhDG9iuYYr4gXYSs1pLYptEC8J6iWpG/qzkwfr4l5Cfg5uF00bbxQE5+WeRaj +YFicvXjB/kcoFZuCL7M/YRXYxkJ/EZ19xI9HZNBQ4L738StkSBKL4OhpF/qgYZ2y +ZLRV6XT4AijUA0Ef7YTuUsTL7Qt9drj09gCtAzXTA7gpZBn5SqT9kWhuwSzY302l +KF8DIC6A52igk2QKPLbleM/V8eCu6n+J4uF+0GwVRROuG7ThxAQiUlJKhoEYrndL +nzT7jHVLftjilhVWFu2On62bRf5t1QZuob+1AdK0ukvEIVsYnN4bnlAkc99Wi6C0 +ZJd9qW5L4A9XAC2gcjr3m0Rzw3RO+k17faR8YfmTuJvGyBf5fnrSFoNkrninXQXp +sk0ajRi4PJ4XTswLyxjWRSt3egNsZBSKnVCibca/QoDEdZHSKXo2FlYiUYx8JHQX +SPUsLl9OQKC1W8/+ReryqBLHCkiGEsvT8gVaXga0uhVaqe+PaVur2tbOHl4yCysC ++ZlnKwsC84LQsUvpENdCh+D7E1I1Rao9IJMR6q9azKq8Ck63cOJ1fA9xSnxJGoCA +IlGLttlXrR32EtzYwEnlqf1nI/IqNQrAXQKrP5VPzHsgMFu5uD4OEZa92Q5cVTsz +ap/1UEqiJVYUt6nuA+aqOUlyjC0oNtYL/VO4DbHTFcHa8SI2cPSS6ebPMWPGHjUm +l9bWa6Q9iyplCYS6hinAVsAaLVjPi1Eu9Pc8rxFCmoiJYJju5NZuGI5UBK64dqcX +T6trWl0kB8QY63JtnrZaoStoSPImV5KVseUKDV8TM3Y76h1nLV3MSmAD1ivk9oKs +VKeVrDhZBWUq9Dqre/+lVGO0a2wo5VTR8hfpf8QkODPLeyNZNdfGKzkkFLuXa8V5 +ELhLQJ3FnbEU3NEvMwikV9MhP/ELPTkZwJr/NKv+9JLs9eXtwz29I/Q8byQVrCCs +hAuDl0zHGRnqdpdSImeS2EXGx631zGMwSe8fhKelni5h6hXrXz52asr0k30BxWjf +WUn1uTInwVjWGy9B5j3mZlVDotFbvVAZgtR0IoFwihPl4VZd9oS13l+hMfrTy1YZ +8xFNg8ZqUQ0lSmKfOVqSBT0lP8tM8LuGxgY4cWluhsAQxR5Nl7wkundnqjcwEDDu +Jz2rD54St1EZYGLDJZSfC7mpG2PgodsdeopQCTyFhHWa8s3caZ40GFOwaR+/5+YF +1oRvkR1Yr4qIS7KbX4xsaFfAA5b8QfLA74L05PAgDwKofam2GFAlAKHOcI6mexPq +aySON9MNdnXBNxs16mBJLzCX5ljQb0ilJildVEI3aVmABptM4ehEiw== +-----END RSA PRIVATE KEY----- diff --git a/setup/db/db/schema-421to430.sql b/setup/db/db/schema-421to430.sql index 7bacefe31b0..53cd0bf594f 100644 --- a/setup/db/db/schema-421to430.sql +++ b/setup/db/db/schema-421to430.sql @@ -41,6 +41,8 @@ ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state_update_count` INT DEFA ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_host` bigint unsigned; ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__power_host` FOREIGN KEY (`power_host`) REFERENCES `cloud`.`host`(`id`); +ALTER TABLE `cloud`.`load_balancing_rules` ADD COLUMN `lb_protocol` VARCHAR(40); + DROP TABLE IF EXISTS `cloud`.`vm_snapshot_details`; CREATE TABLE `cloud`.`vm_snapshot_details` ( `id` bigint unsigned UNIQUE NOT NULL, @@ -464,6 +466,32 @@ CREATE VIEW `cloud`.`storage_pool_view` AS and async_job.instance_type = 'StoragePool' and async_job.job_status = 0; + +CREATE TABLE `sslcerts` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `uuid` varchar(40) DEFAULT NULL, + `account_id` bigint(20) unsigned NOT NULL, + `domain_id` bigint(20) unsigned NOT NULL, + `certificate` text NOT NULL, + `fingerprint` varchar(62) NOT NULL, + `key` text NOT NULL, + `chain` text, + `password` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_sslcert__account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_sslcert__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain` (`id`) ON DELETE CASCADE +); + +CREATE TABLE `load_balancer_cert_map` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `uuid` varchar(40) DEFAULT NULL, + `load_balancer_id` bigint(20) unsigned NOT NULL, + `certificate_id` bigint(20) unsigned NOT NULL, + `revoke` tinyint(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + CONSTRAINT `fk_load_balancer_cert_map__certificate_id` FOREIGN KEY (`certificate_id`) REFERENCES `sslcerts` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_load_balancer_cert_map__load_balancer_id` FOREIGN KEY (`load_balancer_id`) REFERENCES `load_balancing_rules` (`id`) ON DELETE CASCADE); + ALTER TABLE `cloud`.`host` ADD COLUMN `cpu_sockets` int(10) unsigned DEFAULT NULL COMMENT "the number of CPU sockets on the host" AFTER pod_id; DROP VIEW IF EXISTS `cloud`.`host_view`; diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index f5904250bb4..8a351097845 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -52,6 +52,7 @@ import com.cloud.utils.script.Script; public class NetUtils { protected final static Logger s_logger = Logger.getLogger(NetUtils.class); public final static String HTTP_PORT = "80"; + public final static String HTTPS_PORT = "443"; public final static int VPN_PORT = 500; public final static int VPN_NATT_PORT = 4500; public final static int VPN_L2TP_PORT = 1701; @@ -61,6 +62,8 @@ public class NetUtils { public final static String ANY_PROTO = "any"; public final static String ICMP_PROTO = "icmp"; public final static String ALL_PROTO = "all"; + public final static String HTTP_PROTO = "http"; + public final static String SSL_PROTO = "ssl"; public final static String ALL_CIDRS = "0.0.0.0/0"; public final static int PORT_RANGE_MIN = 0;