Creating security groups automatically for load balancers.
Project: http://git-wip-us.apache.org/repos/asf/stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/f6396ffe Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/f6396ffe Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/f6396ffe Branch: refs/heads/gsoc-projects-2015 Commit: f6396ffe9b90c84b755eb8aa7685103073946b1d Parents: c979a0d Author: swapnilpatilRajaram <[email protected]> Authored: Wed Jul 29 08:12:27 2015 +0000 Committer: swapnilpatilRajaram <[email protected]> Committed: Wed Jul 29 08:12:27 2015 +0000 ---------------------------------------------------------------------- .../aws-extension/src/main/assembly/bin.xml | 2 +- .../aws-extension/src/main/bin/aws-extension.sh | 2 +- .../aws-extension/src/main/conf/aws.properties | 6 + .../apache/stratos/aws/extension/AWSHelper.java | 159 ++++++++++++++++--- .../stratos/aws/extension/AWSLoadBalancer.java | 11 +- .../apache/stratos/aws/extension/Constants.java | 4 +- 6 files changed, 153 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/stratos/blob/f6396ffe/extensions/load-balancer/aws-extension/src/main/assembly/bin.xml ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/aws-extension/src/main/assembly/bin.xml b/extensions/load-balancer/aws-extension/src/main/assembly/bin.xml index 036ad1c..ba0ad12 100644 --- a/extensions/load-balancer/aws-extension/src/main/assembly/bin.xml +++ b/extensions/load-balancer/aws-extension/src/main/assembly/bin.xml @@ -41,7 +41,7 @@ <include>jndi.properties</include> <include>log4j.properties</include> <include>thrift-client-config.xml</include> - <include>aws-credentials.conf</include> + <include>aws.properties</include> </includes> </fileSet> <fileSet> http://git-wip-us.apache.org/repos/asf/stratos/blob/f6396ffe/extensions/load-balancer/aws-extension/src/main/bin/aws-extension.sh ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/aws-extension/src/main/bin/aws-extension.sh b/extensions/load-balancer/aws-extension/src/main/bin/aws-extension.sh index 4451ace..19936ae 100755 --- a/extensions/load-balancer/aws-extension/src/main/bin/aws-extension.sh +++ b/extensions/load-balancer/aws-extension/src/main/bin/aws-extension.sh @@ -26,7 +26,7 @@ lib_path=${script_path}/../lib/ class_path=`echo ${lib_path}/*.jar | tr ' ' ':'` properties="-Djndi.properties.dir=${script_path}/../conf -Dlog4j.properties.file.path=${script_path}/../conf/log4j.properties - -Daws.credentials.file=${script_path}/../conf/aws-credentials.conf + -Daws.properties.file=${script_path}/../conf/aws.properties -Djavax.net.ssl.trustStore=${script_path}/../security/client-truststore.jks -Djavax.net.ssl.trustStorePassword=wso2carbon -Dthrift.client.config.file.path=${script_path}/../conf/thrift-client-config.xml http://git-wip-us.apache.org/repos/asf/stratos/blob/f6396ffe/extensions/load-balancer/aws-extension/src/main/conf/aws.properties ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/aws-extension/src/main/conf/aws.properties b/extensions/load-balancer/aws-extension/src/main/conf/aws.properties new file mode 100644 index 0000000..05ebded --- /dev/null +++ b/extensions/load-balancer/aws-extension/src/main/conf/aws.properties @@ -0,0 +1,6 @@ +access-key= +secret-key= +# load-balancer-prefix should contain only alphabets and dashes and should not exceed 25 characters. +load-balancer-prefix=LB- +# security group will be created if does not exist. Should contain only ASCII characters and should not exceed 255 characters. +load-balancer-security-group-name=lb-security-group \ No newline at end of file http://git-wip-us.apache.org/repos/asf/stratos/blob/f6396ffe/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSHelper.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSHelper.java b/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSHelper.java index 1520674..f2e742c 100644 --- a/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSHelper.java +++ b/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSHelper.java @@ -28,6 +28,7 @@ import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,6 +37,11 @@ import org.apache.stratos.load.balancer.extension.api.exception.LoadBalancerExte import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.ec2.AmazonEC2Client; +import com.amazonaws.services.ec2.model.AuthorizeSecurityGroupIngressRequest; +import com.amazonaws.services.ec2.model.CreateSecurityGroupRequest; +import com.amazonaws.services.ec2.model.CreateSecurityGroupResult; +import com.amazonaws.services.ec2.model.IpPermission; import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingClient; import com.amazonaws.services.elasticloadbalancing.model.*; @@ -45,11 +51,16 @@ public class AWSHelper { private String lbPrefix; private int lbSequence; private Object lbSequenceMutex; + private String lbSecurityGroupName; + private String lbSecurityGroupDescription; + + private ConcurrentHashMap<String, String> regionToSecurityGroupIdMap; private BasicAWSCredentials awsCredentials; private ClientConfiguration clientConfiguration; AmazonElasticLoadBalancingClient lbClient; + AmazonEC2Client ec2Client; private static final Log log = LogFactory.getLog(AWSHelper.class); @@ -57,15 +68,15 @@ public class AWSHelper { // Read values for awsAccessKey, awsSecretKey etc. from config file // Throw a proper exception / log warning if cant read credentials ? - String awsCredentialsFile = System - .getProperty(Constants.AWS_CREDENTIALS_FILE); + String awsPropertiesFile = System + .getProperty(Constants.AWS_PROPERTIES_FILE); Properties properties = new Properties(); InputStream inputStream = null; try { - inputStream = new FileInputStream(awsCredentialsFile); + inputStream = new FileInputStream(awsPropertiesFile); properties.load(inputStream); @@ -74,27 +85,42 @@ public class AWSHelper { this.awsSecretKey = properties .getProperty(Constants.AWS_SECRET_KEY); - if(this.awsAccessKey.isEmpty() || this.awsSecretKey.isEmpty()) - { - throw new LoadBalancerExtensionException("Invalid AWS credentials."); + if (this.awsAccessKey.isEmpty() || this.awsSecretKey.isEmpty()) { + throw new LoadBalancerExtensionException( + "Invalid AWS credentials."); } this.lbPrefix = properties.getProperty(Constants.LB_PREFIX); - if(this.lbPrefix.isEmpty() || this.lbPrefix.length() > 25) - { - throw new LoadBalancerExtensionException("Invalid load balancer prefix."); + if (this.lbPrefix.isEmpty() || this.lbPrefix.length() > 25) { + throw new LoadBalancerExtensionException( + "Invalid load balancer prefix."); } lbSequence = 0; lbSequenceMutex = new Object(); + this.lbSecurityGroupName = properties + .getProperty(Constants.LOAD_BALANCER_SECURITY_GROUP_NAME); + + if (this.lbSecurityGroupName.isEmpty() + || this.lbSecurityGroupName.length() > 255) { + throw new LoadBalancerExtensionException( + "Invalid load balancer security group name."); + } + + this.lbSecurityGroupDescription = Constants.LOAD_BALANCER_SECURITY_GROUP_DESCRIPTION; + + regionToSecurityGroupIdMap = new ConcurrentHashMap<String, String>(); + awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey); clientConfiguration = new ClientConfiguration(); lbClient = new AmazonElasticLoadBalancingClient(awsCredentials, clientConfiguration); + ec2Client = new AmazonEC2Client(awsCredentials, clientConfiguration); + } catch (IOException e) { log.error("Error reading aws configuration file."); throw new LoadBalancerExtensionException( @@ -108,8 +134,7 @@ public class AWSHelper { } } - public int getNextLBSequence() - { + public int getNextLBSequence() { synchronized (lbSequenceMutex) { lbSequence++; return lbSequence; @@ -140,10 +165,16 @@ public class AWSHelper { createLoadBalancerRequest.setAvailabilityZones(availabilityZones); - lbClient.setEndpoint("elasticloadbalancing." + region - + ".amazonaws.com"); - try { + String securityGroupId = getSecurityGroupIdForRegion(region); + + List<String> securityGroups = new ArrayList<String>(); + securityGroups.add(securityGroupId); + + createLoadBalancerRequest.setSecurityGroups(securityGroups); + + lbClient.setEndpoint("elasticloadbalancing." + region + + ".amazonaws.com"); CreateLoadBalancerResult clbResult = lbClient .createLoadBalancer(createLoadBalancerRequest); @@ -206,7 +237,7 @@ public class AWSHelper { try { lbClient.setEndpoint("elasticloadbalancing." + region + ".amazonaws.com"); - + RegisterInstancesWithLoadBalancerResult result = lbClient .registerInstancesWithLoadBalancer(registerInstancesWithLoadBalancerRequest); return; @@ -239,7 +270,7 @@ public class AWSHelper { try { lbClient.setEndpoint("elasticloadbalancing." + region + ".amazonaws.com"); - + DeregisterInstancesFromLoadBalancerResult result = lbClient .deregisterInstancesFromLoadBalancer(deregisterInstancesFromLoadBalancerRequest); return; @@ -272,7 +303,7 @@ public class AWSHelper { try { lbClient.setEndpoint("elasticloadbalancing." + region + ".amazonaws.com"); - + DescribeLoadBalancersResult result = lbClient .describeLoadBalancers(describeLoadBalancersRequest); @@ -297,9 +328,11 @@ public class AWSHelper { * @param region * @return list of instances attached */ - public List<Instance> getAttachedInstances(String loadBalancerName, String region) { + public List<Instance> getAttachedInstances(String loadBalancerName, + String region) { try { - LoadBalancerDescription lbDescription = getLoadBalancerDescription(loadBalancerName, region); + LoadBalancerDescription lbDescription = getLoadBalancerDescription( + loadBalancerName, region); if (lbDescription == null) { log.warn("Could not find description of load balancer " @@ -398,9 +431,11 @@ public class AWSHelper { * @param region * @return list of instances attached to load balancer */ - public List<Listener> getAttachedListeners(String loadBalancerName, String region) { + public List<Listener> getAttachedListeners(String loadBalancerName, + String region) { try { - LoadBalancerDescription lbDescription = getLoadBalancerDescription(loadBalancerName, region); + LoadBalancerDescription lbDescription = getLoadBalancerDescription( + loadBalancerName, region); if (lbDescription == null) { log.warn("Could not find description of load balancer " @@ -427,6 +462,80 @@ public class AWSHelper { } + public String createSecurityGroup(String groupName, String description, + String region) throws LoadBalancerExtensionException { + if (groupName == null || groupName.isEmpty()) { + throw new LoadBalancerExtensionException( + "Invalid Security Group Name."); + } + + CreateSecurityGroupRequest createSecurityGroupRequest = new CreateSecurityGroupRequest(); + createSecurityGroupRequest.setGroupName(groupName); + createSecurityGroupRequest.setDescription(description); + + try { + ec2Client.setEndpoint("ec2." + region + ".amazonaws.com"); + + CreateSecurityGroupResult createSecurityGroupResult = ec2Client + .createSecurityGroup(createSecurityGroupRequest); + + return createSecurityGroupResult.getGroupId(); + + } catch (Exception e) { + e.printStackTrace(); + throw new LoadBalancerExtensionException( + "Could not create security group."); + } + + } + + public void addInboundRuleToSecurityGroup(String groupId, String region) + throws LoadBalancerExtensionException { + if (groupId == null || groupId.isEmpty()) { + throw new LoadBalancerExtensionException( + "Invalid security group Id for addInboundRuleToSecurityGroup."); + } + + AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = new AuthorizeSecurityGroupIngressRequest(); + authorizeSecurityGroupIngressRequest.setGroupId(groupId); + authorizeSecurityGroupIngressRequest.setCidrIp("0.0.0.0/0"); + authorizeSecurityGroupIngressRequest.setFromPort(0); + authorizeSecurityGroupIngressRequest.setToPort(65535); + authorizeSecurityGroupIngressRequest.setIpProtocol("tcp"); + + try { + ec2Client.setEndpoint("ec2." + region + ".amazonaws.com"); + + ec2Client + .authorizeSecurityGroupIngress(authorizeSecurityGroupIngressRequest); + + } catch (Exception e) { + throw new LoadBalancerExtensionException( + "Could not add inbound rule to security group " + groupId + + "."); + } + } + + public String getSecurityGroupIdForRegion(String region) + throws LoadBalancerExtensionException { + if (region == null) + return null; + + if (this.regionToSecurityGroupIdMap.contains(region)) { + return this.regionToSecurityGroupIdMap.get(region); + } else { + String securityGroupId = createSecurityGroup( + this.lbSecurityGroupName, this.lbSecurityGroupDescription, + region); + this.regionToSecurityGroupIdMap.put(region, securityGroupId); + + // Also add the inbound rule + addInboundRuleToSecurityGroup(securityGroupId, region); + + return securityGroupId; + } + } + /** * Returns the Listeners required for the service. Listeners are derived * from the proxy port, port and protocol values of the service. @@ -461,13 +570,15 @@ public class AWSHelper { * @return name of the load balancer * @throws LoadBalancerExtensionException */ - public String generateLoadBalancerName() throws LoadBalancerExtensionException { + public String generateLoadBalancerName() + throws LoadBalancerExtensionException { String name = null; name = lbPrefix + getNextLBSequence(); - if(name.length() > 32) - throw new LoadBalancerExtensionException("Load balanacer name length exceeded"); + if (name.length() > 32) + throw new LoadBalancerExtensionException( + "Load balanacer name length exceeded"); return name; } http://git-wip-us.apache.org/repos/asf/stratos/blob/f6396ffe/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSLoadBalancer.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSLoadBalancer.java b/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSLoadBalancer.java index 7bf93e8..4eff571 100644 --- a/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSLoadBalancer.java +++ b/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/AWSLoadBalancer.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -39,12 +40,12 @@ public class AWSLoadBalancer implements LoadBalancer { private static final Log log = LogFactory.getLog(AWSLoadBalancer.class); // A map <clusterId, load balancer id> - private HashMap<String, LoadBalancerInfo> clusterIdToLoadBalancerMap; + private ConcurrentHashMap<String, LoadBalancerInfo> clusterIdToLoadBalancerMap; private AWSHelper awsHelper; public AWSLoadBalancer() throws LoadBalancerExtensionException { - clusterIdToLoadBalancerMap = new HashMap<String, LoadBalancerInfo>(); + clusterIdToLoadBalancerMap = new ConcurrentHashMap<String, LoadBalancerInfo>(); awsHelper = new AWSHelper(); } @@ -151,7 +152,8 @@ public class AWSLoadBalancer implements LoadBalancer { List<Listener> listenersToAddToLoadBalancer = new ArrayList<Listener>(); List<Listener> listenersForThisCluster = awsHelper - .getRequiredListeners(clusterMembers.iterator().next()); + .getRequiredListeners(clusterMembers.iterator() + .next()); for (Listener listener : listenersForThisCluster) { if (attachedListeners == null @@ -195,7 +197,8 @@ public class AWSLoadBalancer implements LoadBalancer { .iterator().next().getInstanceId()); List<Listener> listenersForThisCluster = awsHelper - .getRequiredListeners(clusterMembers.iterator().next()); + .getRequiredListeners(clusterMembers.iterator() + .next()); String loadBalancerDNSName = awsHelper .createLoadBalancer(loadBalancerName, http://git-wip-us.apache.org/repos/asf/stratos/blob/f6396ffe/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/Constants.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/Constants.java b/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/Constants.java index d03915c..f3ffb94 100644 --- a/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/Constants.java +++ b/extensions/load-balancer/aws-extension/src/main/java/org/apache/stratos/aws/extension/Constants.java @@ -29,8 +29,10 @@ public class Constants { public static final String NETWORK_PARTITION_ID = "network.partition.id"; public static final String CLUSTER_ID = "cluster.id"; public static final String SERVICE_NAME = "service.name"; - public static final String AWS_CREDENTIALS_FILE="aws.credentials.file"; + public static final String AWS_PROPERTIES_FILE="aws.properties.file"; public static final String AWS_ACCESS_KEY = "access-key"; public static final String AWS_SECRET_KEY = "secret-key"; public static final String LB_PREFIX = "load-balancer-prefix"; + public static final String LOAD_BALANCER_SECURITY_GROUP_NAME = "load-balancer-security-group-name"; + public static final String LOAD_BALANCER_SECURITY_GROUP_DESCRIPTION = "Security group for load balancers created for Apache Stratos."; }
