/************************************************************************* * Copyright 2009-2014 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. ************************************************************************/ package com.eucalyptus.loadbalancing; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import org.apache.log4j.Logger; import com.eucalyptus.entities.Entities; import com.eucalyptus.entities.TransactionResource; import com.eucalyptus.loadbalancing.LoadBalancerBackendServerDescription.LoadBalancerBackendServerDescriptionCoreView; import com.eucalyptus.loadbalancing.LoadBalancerBackendServerDescription.LoadBalancerBackendServerDescriptionEntityTransform; import com.eucalyptus.loadbalancing.LoadBalancerListener.LoadBalancerListenerCoreView; import com.eucalyptus.loadbalancing.LoadBalancerListener.PROTOCOL; import com.eucalyptus.loadbalancing.LoadBalancerPolicyAttributeDescription.LoadBalancerPolicyAttributeDescriptionCoreView; import com.eucalyptus.loadbalancing.LoadBalancerPolicyAttributeTypeDescription.Cardinality; import com.eucalyptus.loadbalancing.LoadBalancerPolicyAttributeTypeDescription.LoadBalancerPolicyAttributeTypeDescriptionCoreView; import com.eucalyptus.loadbalancing.LoadBalancerPolicyDescription.LoadBalancerPolicyDescriptionCoreView; import com.eucalyptus.loadbalancing.LoadBalancerPolicyDescription.LoadBalancerPolicyDescriptionEntityTransform; import com.eucalyptus.loadbalancing.common.msgs.PolicyAttribute; import com.eucalyptus.loadbalancing.common.msgs.PolicyAttributeDescription; import com.eucalyptus.loadbalancing.common.msgs.PolicyAttributeDescriptions; import com.eucalyptus.loadbalancing.common.msgs.PolicyAttributeTypeDescription; import com.eucalyptus.loadbalancing.common.msgs.PolicyAttributeTypeDescriptions; import com.eucalyptus.loadbalancing.common.msgs.PolicyDescription; import com.eucalyptus.loadbalancing.common.msgs.PolicyTypeDescription; import com.eucalyptus.loadbalancing.service.DuplicatePolicyNameException; import com.eucalyptus.loadbalancing.service.InvalidConfigurationRequestException; import com.eucalyptus.loadbalancing.service.LoadBalancingException; import com.eucalyptus.loadbalancing.service.PolicyTypeNotFoundException; import com.eucalyptus.system.BaseDirectory; import com.eucalyptus.util.Exceptions; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Collections2; import com.google.common.collect.Sets; import com.google.common.base.Predicate; /** * @author Sang-Min Park * */ public class LoadBalancerPolicies { private static Logger LOG = Logger.getLogger( LoadBalancerPolicies.class ); public static String LATEST_SECURITY_POLICY_NAME = null; /** * initialize the policy types that ELB will support * this method is idempotent */ public static void initialize(){ final List<LoadBalancerPolicyTypeDescription> requiredPolicyTypes = Lists.newArrayList(initialize42()); for(final LoadBalancerPolicyTypeDescription policyType : requiredPolicyTypes){ try ( final TransactionResource db = Entities.transactionFor( LoadBalancerPolicyTypeDescription.class ) ) { try { Entities.uniqueResult( policyType ); }catch( final NoSuchElementException ex ){ Entities.persist( policyType ); db.commit(); LOG.debug(String.format("New policy type has been added: %s", policyType)); } }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } } // initialize ELB policy types in version 4.0 private static List<LoadBalancerPolicyTypeDescription> initialize40(){ final List<LoadBalancerPolicyTypeDescription> requiredPolicyTypes = Lists.newArrayList(); requiredPolicyTypes.add( new LoadBalancerPolicyTypeDescription("AppCookieStickinessPolicyType", "Stickiness policy with session lifetimes controlled by the lifetime of the application-generated cookie. This policy can be associated only with HTTP/HTTPS listeners.", Lists.newArrayList( new LoadBalancerPolicyAttributeTypeDescription("CookieName", "String", LoadBalancerPolicyAttributeTypeDescription.Cardinality.ONE)))); requiredPolicyTypes.add( new LoadBalancerPolicyTypeDescription("LBCookieStickinessPolicyType", "Stickiness policy with session lifetimes controlled by the browser (user-agent) or a specified expiration period. This policy can be associated only with HTTP/HTTPS listeners.", Lists.newArrayList( new LoadBalancerPolicyAttributeTypeDescription("CookieExpirationPeriod", "Long", LoadBalancerPolicyAttributeTypeDescription.Cardinality.ZERO_OR_ONE)))); return requiredPolicyTypes; } final static List<String> cipherNamesIn42 = Lists.newArrayList( "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-ECDSA-AES128-SHA256", "ECDHE-RSA-AES128-SHA256", "ECDHE-ECDSA-AES128-SHA", "ECDHE-RSA-AES128-SHA", "DHE-RSA-AES128-SHA", "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-ECDSA-AES256-SHA384", "ECDHE-RSA-AES256-SHA384", "ECDHE-RSA-AES256-SHA", "ECDHE-ECDSA-AES256-SHA", "AES128-GCM-SHA256", "AES128-SHA256", "AES128-SHA", "AES256-GCM-SHA384", "AES256-SHA256", "AES256-SHA", "DHE-DSS-AES128-SHA", "CAMELLIA128-SHA", "EDH-RSA-DES-CBC3-SHA", "DES-CBC3-SHA", "ECDHE-RSA-RC4-SHA", "RC4-SHA", "ECDHE-ECDSA-RC4-SHA", "DHE-DSS-AES256-GCM-SHA384", "DHE-RSA-AES256-GCM-SHA384", "DHE-RSA-AES256-SHA256", "DHE-DSS-AES256-SHA256", "DHE-RSA-AES256-SHA", "DHE-DSS-AES256-SHA", "DHE-RSA-CAMELLIA256-SHA", "DHE-DSS-CAMELLIA256-SHA", "CAMELLIA256-SHA", "EDH-DSS-DES-CBC3-SHA", "DHE-DSS-AES128-GCM-SHA256", "DHE-RSA-AES128-GCM-SHA256", "DHE-RSA-AES128-SHA256", "DHE-DSS-AES128-SHA256", "DHE-RSA-CAMELLIA128-SHA", "DHE-DSS-CAMELLIA128-SHA", "ADH-AES128-GCM-SHA256", "ADH-AES128-SHA", "ADH-AES128-SHA256", "ADH-AES256-GCM-SHA384", "ADH-AES256-SHA", "ADH-AES256-SHA256", "ADH-CAMELLIA128-SHA", "ADH-CAMELLIA256-SHA", "ADH-DES-CBC3-SHA", "ADH-DES-CBC-SHA", "ADH-RC4-MD5", "ADH-SEED-SHA", "DES-CBC-SHA", "DHE-DSS-SEED-SHA", "DHE-RSA-SEED-SHA", "EDH-DSS-DES-CBC-SHA", "EDH-RSA-DES-CBC-SHA", "IDEA-CBC-SHA", "RC4-MD5", "SEED-SHA", "DES-CBC3-MD5", "DES-CBC-MD5", "RC2-CBC-MD5", "PSK-AES256-CBC-SHA", "PSK-3DES-EDE-CBC-SHA", "KRB5-DES-CBC3-SHA", "KRB5-DES-CBC3-MD5", "PSK-AES128-CBC-SHA", "PSK-RC4-SHA", "KRB5-RC4-SHA", "KRB5-RC4-MD5", "KRB5-DES-CBC-SHA", "KRB5-DES-CBC-MD5", "EXP-EDH-RSA-DES-CBC-SHA", "EXP-EDH-DSS-DES-CBC-SHA", "EXP-ADH-DES-CBC-SHA", "EXP-DES-CBC-SHA", "EXP-RC2-CBC-MD5", "EXP-KRB5-RC2-CBC-SHA", "EXP-KRB5-DES-CBC-SHA", "EXP-KRB5-RC2-CBC-MD5", "EXP-KRB5-DES-CBC-MD5", "EXP-ADH-RC4-MD5", "EXP-RC4-MD5", "EXP-KRB5-RC4-SHA", "EXP-KRB5-RC4-MD5" ); private static List<LoadBalancerPolicyTypeDescription> initialize42(){ final List<LoadBalancerPolicyTypeDescription> requiredPolicyTypes = initialize40(); final LoadBalancerPolicyTypeDescription sslNego = new LoadBalancerPolicyTypeDescription( "SSLNegotiationPolicyType", "Listener policy that defines the ciphers and protocols that will be accepted by the load balancer. This policy can be associated only with HTTPS/SSL listeners." ); final List<LoadBalancerPolicyAttributeTypeDescription> sslNegoAttributeTypes = Lists.newArrayList( new LoadBalancerPolicyAttributeTypeDescription("Protocol-SSLv2", "Boolean", Cardinality.ZERO_OR_ONE), new LoadBalancerPolicyAttributeTypeDescription("Protocol-TLSv1", "Boolean", Cardinality.ZERO_OR_ONE), new LoadBalancerPolicyAttributeTypeDescription("Protocol-SSLv3", "Boolean", Cardinality.ZERO_OR_ONE), new LoadBalancerPolicyAttributeTypeDescription("Protocol-TLSv1.1", "Boolean", Cardinality.ZERO_OR_ONE, "A description for Protocol-TLSv1.1"), new LoadBalancerPolicyAttributeTypeDescription("Protocol-TLSv1.2", "Boolean", Cardinality.ZERO_OR_ONE, "A description for Protocol-TLSv1.2"), new LoadBalancerPolicyAttributeTypeDescription("Reference-Security-Policy", "String", Cardinality.ZERO_OR_ONE, "The value of this attribute is the name of our sample policy (referring to our sample policy"), new LoadBalancerPolicyAttributeTypeDescription("Server-Defined-Cipher-Order", "Boolean", Cardinality.ZERO_OR_ONE, "The value true means the policy will follow the cipher order") ); for(final String name : cipherNamesIn42){ sslNegoAttributeTypes.add(new LoadBalancerPolicyAttributeTypeDescription(name, "Boolean", Cardinality.ZERO_OR_ONE, String.format("A description for %s", name))); } for(final LoadBalancerPolicyAttributeTypeDescription attrType : sslNegoAttributeTypes){ sslNego.addPolicyAttributeTypeDescription(attrType); } // policy type for ssl protocol/cipher negotiation requiredPolicyTypes.add(sslNego); // policy type for backend server authentication requiredPolicyTypes.add(new LoadBalancerPolicyTypeDescription( "BackendServerAuthenticationPolicyType", "Policy that controls authentication to back-end server(s) and contains one or more policies, such as an instance of a PublicKeyPolicyType. This policy can be associated only with back-end servers that are using HTTPS/SSL.", Lists.newArrayList( new LoadBalancerPolicyAttributeTypeDescription("PublicKeyPolicyName", "PolicyName", Cardinality.ONE_OR_MORE)) )); requiredPolicyTypes.add(new LoadBalancerPolicyTypeDescription( "ProxyProtocolPolicyType", "Policy that controls whether to include the IP address and port of the originating request for TCP messages. This policy operates on TCP/SSL listeners only", Lists.newArrayList( new LoadBalancerPolicyAttributeTypeDescription("ProxyProtocol", "Boolean", Cardinality.ONE)) )); // policy type for containing the list of public key when authenticating back-end servers requiredPolicyTypes.add(new LoadBalancerPolicyTypeDescription( "PublicKeyPolicyType", "Policy containing a list of public keys to accept when authenticating the back-end server(s). This policy cannot be applied directly to back-end servers or listeners but must be part of a BackendServerAuthenticationPolicyType.", Lists.newArrayList( new LoadBalancerPolicyAttributeTypeDescription("PublicKey", "String", Cardinality.ONE)) )); return requiredPolicyTypes; } public static List<LoadBalancerPolicyTypeDescription> getLoadBalancerPolicyTypeDescriptions(){ try ( final TransactionResource db = Entities.transactionFor( LoadBalancerPolicyTypeDescription.class ) ) { return Entities.query(new LoadBalancerPolicyTypeDescription()); }catch(final NoSuchElementException ex){ return Lists.newArrayList(); }catch(final Exception ex){ throw ex; } } public static LoadBalancerPolicyTypeDescription findLoadBalancerPolicyTypeDescription(final String policyTypeName) throws NoSuchElementException { try ( final TransactionResource db = Entities.transactionFor( LoadBalancerPolicyTypeDescription.class ) ) { return Entities.uniqueResult(LoadBalancerPolicyTypeDescription.named(policyTypeName)); }catch(final NoSuchElementException ex){ throw ex; }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } public static boolean isAttributeValueValid(final String attrType, final String cardinality, final String attrValue){ if(attrType ==null) return true; try{ if(attrType.toLowerCase().equals("boolean")){ Boolean.parseBoolean(attrValue); }else if(attrType.toLowerCase().equals("integer")){ Integer.parseInt(attrValue); }else if(attrType.toLowerCase().equals("long")){ Long.parseLong(attrValue); }else if(attrType.toLowerCase().equals("string")){ ; } }catch(final Exception ex){ return false; } return true; } public static void addLoadBalancerPolicy(final LoadBalancer lb, final String policyName, final String policyTypeName, final List<PolicyAttribute> policyAttributes) throws LoadBalancingException { for(final LoadBalancerPolicyDescriptionCoreView current : lb.getPolicies()){ if(policyName.equals(current.getPolicyName())) throw new DuplicatePolicyNameException(); } LoadBalancerPolicyTypeDescription policyType = null; for(final LoadBalancerPolicyTypeDescription type : getLoadBalancerPolicyTypeDescriptions()){ if(policyTypeName.equals(type.getPolicyTypeName())){ policyType = type; break; } } if(policyType == null) throw new PolicyTypeNotFoundException(); List<PolicyAttribute> attributes = null; // Check Reference-Security-Policy if ("SSLNegotiationPolicyType".equals(policyType.getPolicyTypeName())) { String refPolicy = null; for(final PolicyAttribute attr : policyAttributes) { if("Reference-Security-Policy".equals(attr.getAttributeName())) { refPolicy = attr.getAttributeValue(); break; } } if(refPolicy!=null) { PolicyDescription predefinedPolicy = null; List<PolicyDescription> predefinedPolicies = LoadBalancerPolicies.getSamplePolicyDescription(); for(final PolicyDescription policy : predefinedPolicies) { if(refPolicy.equals(policy.getPolicyName())) { predefinedPolicy = policy; break; } } if (predefinedPolicy == null) { throw new InvalidConfigurationRequestException(String.format("Referenced security policy %s is not found", refPolicy)); }else { attributes = Lists.transform(predefinedPolicy.getPolicyAttributeDescriptions().getMember(), new Function<PolicyAttributeDescription,PolicyAttribute>() { @Override public PolicyAttribute apply(PolicyAttributeDescription arg0) { final PolicyAttribute attr = new PolicyAttribute(); attr.setAttributeName(arg0.getAttributeName()); attr.setAttributeValue(arg0.getAttributeValue()); return attr; } }); } } } if(attributes == null) attributes = policyAttributes; /* check for cardinality * ONE(1) : Single value required ZERO_OR_ONE(0..1) : Up to one value can be supplied ZERO_OR_MORE(0..*) : Optional. Multiple values are allowed ONE_OR_MORE(1..*0) : Required. Multiple values are allowed */ final List<LoadBalancerPolicyAttributeTypeDescriptionCoreView> policyAttrTypes = policyType.getPolicyAttributeTypeDescriptions(); for (final LoadBalancerPolicyAttributeTypeDescriptionCoreView policyAttrType : policyAttrTypes) { if("ONE".equals(policyAttrType.getCardinality()) || "ONE_OR_MORE".equals(policyAttrType.getCardinality())) { boolean attrFound = false; for(final PolicyAttribute attr : attributes) { if(policyAttrType.getAttributeName().equals(attr.getAttributeName()) && attr.getAttributeValue()!=null){ attrFound = true; break; } } if (!attrFound) throw new InvalidConfigurationRequestException(String.format("There is no attribute %s found (Cardinality: %s)", policyAttrType.getAttributeName(), policyAttrType.getCardinality())); } // other rules are enforced in addPolicyAttributeDescription } final LoadBalancerPolicyDescription policyDesc = new LoadBalancerPolicyDescription(lb, policyName, policyTypeName); for(final PolicyAttribute attr : attributes){ policyDesc.addPolicyAttributeDescription(attr.getAttributeName(), attr.getAttributeValue()); } try ( final TransactionResource db = Entities.transactionFor( LoadBalancerPolicyDescription.class ) ) { Entities.persist(policyDesc); db.commit(); } } public static void deleteLoadBalancerPolicy(final LoadBalancer lb, final String policyName) throws LoadBalancingException { // FIXME: spark - for some reason, Entities.delete does not delete the queried object // To work around, had to use deleteAll with where clause final List<LoadBalancerPolicyDescription> policies= getLoadBalancerPolicyDescription(lb, Lists.newArrayList(policyName)); if(policies == null || policies.size()<=0) return; final LoadBalancerPolicyDescription toDelete = policies.get(0); // check policy - listener association final List<LoadBalancerListenerCoreView> listeners = toDelete.getListeners(); if(listeners!=null && listeners.size()>0) throw new InvalidConfigurationRequestException("The policy is enabled for listeners"); // check policy - backend association final List<LoadBalancerBackendServerDescriptionCoreView> backends = toDelete.getBackendServers(); if(backends!=null && backends.size()>0) throw new InvalidConfigurationRequestException("The policy is enabled for backend servers"); try ( final TransactionResource db = Entities.transactionFor( LoadBalancerPolicyAttributeDescription.class ) ) { Entities.deleteAllMatching(LoadBalancerPolicyAttributeDescription.class, "WHERE metadata_policy_desc_fk = :metadata_policy_desc_fk", Collections.singletonMap("metadata_policy_desc_fk", toDelete.getRecordId())); db.commit(); }catch(final Exception ex){ LOG.error( "Failed to delete policy attributes", ex ); } try ( final TransactionResource db = Entities.transactionFor( LoadBalancerPolicyDescription.class ) ) { Entities.deleteAllMatching(LoadBalancerPolicyDescription.class, "WHERE unique_name = :unique_name", Collections.singletonMap("unique_name", toDelete.getUniqueName())); db.commit(); }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } public static List<LoadBalancerPolicyDescription> getLoadBalancerPolicyDescription(final LoadBalancer lb){ final List<LoadBalancerPolicyDescriptionCoreView> policyViews = Lists.newArrayList(lb.getPolicies()); final List<LoadBalancerPolicyDescription> policies = Lists.newArrayList(); for(final LoadBalancerPolicyDescriptionCoreView policyView: policyViews){ policies.add(LoadBalancerPolicyDescriptionEntityTransform.INSTANCE.apply(policyView)); } return policies; } public static LoadBalancerPolicyDescription getLoadBalancerPolicyDescription(final LoadBalancer lb, final String policyName) throws NoSuchElementException { LoadBalancerPolicyDescription policy = null; for(final LoadBalancerPolicyDescriptionCoreView p : lb.getPolicies()){ if(p.getPolicyName().equals(policyName)){ policy = LoadBalancerPolicyDescriptionEntityTransform.INSTANCE.apply(p); break; } } if(policy!=null) return policy; else throw new NoSuchElementException(); } public static List<LoadBalancerPolicyDescription> getLoadBalancerPolicyDescription(final LoadBalancer lb, final List<String> policyNames){ final List<LoadBalancerPolicyDescription> allPolicies = getLoadBalancerPolicyDescription(lb); final List<LoadBalancerPolicyDescription> filtered = Lists.newArrayList(Collections2.filter(allPolicies, new Predicate<LoadBalancerPolicyDescription>(){ @Override public boolean apply(LoadBalancerPolicyDescription arg0) { return policyNames.contains(arg0.getPolicyName()); } })); return filtered; } public static List<LoadBalancerPolicyDescription> getPoliciesOfListener(final LoadBalancerListener listener){ try ( final TransactionResource db = Entities.transactionFor( LoadBalancerListener.class ) ) { final LoadBalancerListener found = Entities.uniqueResult(listener); final List<LoadBalancerPolicyDescriptionCoreView> policies=found.getPolicies(); db.commit(); return Lists.transform(policies, LoadBalancerPolicyDescriptionEntityTransform.INSTANCE); }catch(final NoSuchElementException ex){ return Lists.newArrayList(); }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } public static void removePoliciesFromListener(final LoadBalancerListener listener){ try ( final TransactionResource db = Entities.transactionFor( LoadBalancerListener.class ) ) { final LoadBalancerListener update = Entities.uniqueResult(listener); update.resetPolicies(); Entities.persist(update); db.commit(); }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } public static void removePolicyFromListener(final LoadBalancerListener listener, final LoadBalancerPolicyDescription policy){ try ( final TransactionResource db = Entities.transactionFor( LoadBalancerListener.class ) ) { final LoadBalancerListener update = Entities.uniqueResult(listener); update.removePolicy(policy); db.commit(); }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } public static void addPoliciesToBackendServer(final LoadBalancerBackendServerDescription server, final List<LoadBalancerPolicyDescription> policies) throws LoadBalancingException { try ( final TransactionResource db = Entities.transactionFor( LoadBalancerBackendServerDescription.class ) ) { try{ final LoadBalancerBackendServerDescription entity = Entities.uniqueResult(server); for(final LoadBalancerPolicyDescription p : policies) entity.addPolicy(p); Entities.persist(entity); db.commit(); }catch(final NoSuchElementException ex){ throw new InvalidConfigurationRequestException("Backend server description is not found on db"); }catch(final Exception ex){ throw new InvalidConfigurationRequestException("Unknown error ocrrued while updating db"); } } } public static void removePoliciesFromBackendServer(final LoadBalancerBackendServerDescription backend, final List<String> policyNames) throws LoadBalancingException { final List<LoadBalancerPolicyDescription> policyToRemove = Lists.newArrayList(); for(final LoadBalancerPolicyDescriptionCoreView pview : backend.getPolicyDescriptions()) { if(policyNames.contains(pview.getPolicyName())) policyToRemove.add(LoadBalancerPolicyDescriptionEntityTransform.INSTANCE.apply(pview)); } if(policyToRemove.size() < policyNames.size()) throw new InvalidConfigurationRequestException("Unknow policy names found"); try ( final TransactionResource db = Entities.transactionFor( LoadBalancerBackendServerDescription.class ) ) { try{ final LoadBalancerBackendServerDescription entity = Entities.uniqueResult(backend); for(final LoadBalancerPolicyDescription p : policyToRemove) entity.removePolicy(p); Entities.persist(entity); db.commit(); }catch(final NoSuchElementException ex){ throw new InvalidConfigurationRequestException("Backend server description is not found on db"); }catch(final Exception ex){ throw new InvalidConfigurationRequestException("Unknown error ocrrued while updating db"); } } } public static void clearPoliciesFromBackendServer(final LoadBalancerBackendServerDescription backend) throws LoadBalancingException { if (backend == null) throw new InvalidConfigurationRequestException("Backend server description is not found"); final List<String> allPolicies = Lists.transform( backend.getPolicyDescriptions(), new Function<LoadBalancerPolicyDescriptionCoreView, String> () { @Override public String apply(LoadBalancerPolicyDescriptionCoreView arg0) { return arg0.getPolicyName(); } }); removePoliciesFromBackendServer(backend, allPolicies); } public static void addPoliciesToListener(final LoadBalancerListener listener, final List<LoadBalancerPolicyDescription> policies) throws LoadBalancingException{ // either one not both of LBCookieStickinessPolicy and AppCookieStickinessPolicy is allowed if(policies!=null && policies.size()>0){ int numCookies = 0; for(final LoadBalancerPolicyDescription policy : policies){ if("LBCookieStickinessPolicyType".equals(policy.getPolicyTypeName())){ numCookies ++; if( !( listener.getProtocol().equals(PROTOCOL.HTTP) || listener.getProtocol().equals(PROTOCOL.HTTPS))) throw new InvalidConfigurationRequestException("Session stickiness policy can be associated with only HTTP/HTTPS"); } else if("AppCookieStickinessPolicyType".equals(policy.getPolicyTypeName())){ numCookies ++; if( !( listener.getProtocol().equals(PROTOCOL.HTTP) || listener.getProtocol().equals(PROTOCOL.HTTPS))) throw new InvalidConfigurationRequestException("Session stickiness policy can be associated with only HTTP/HTTPS"); } } if(numCookies > 1){ throw new InvalidConfigurationRequestException("Only one cookie stickiness policy can be set"); } } try ( final TransactionResource db = Entities.transactionFor( LoadBalancerListener.class ) ) { final LoadBalancerListener update = Entities.uniqueResult(listener); for(final LoadBalancerPolicyDescription policy : policies){ update.removePolicy(policy); update.addPolicy(policy); } db.commit(); }catch(final Exception ex){ throw Exceptions.toUndeclared(ex); } } public static List<PolicyDescription> getSamplePolicyDescription(){ return Lists.newArrayList(getSamplePolicyDescription42()); } private static class AttributeNameValuePair { @JsonProperty("AttributeName") public String AttributeName = null; @JsonProperty("AttributeValue") public String AttributeValue = null; } private static class SSLSecurityPolicy { @JsonProperty("PolicyName") public String PolicyName = null; @JsonProperty("PolicyTypeName") public String PolicyTypeName = null; @JsonProperty("PolicyAttributeDescriptions") public List<AttributeNameValuePair> PolicyAttributeDescriptions = null; } private static PolicyDescription getPolicyDescription(final String pathToAttributeJson) { try{ final InputStream fileStream = new FileInputStream(pathToAttributeJson); final ObjectMapper objectMapper = new ObjectMapper(); final SSLSecurityPolicy policy = objectMapper.readValue(fileStream, SSLSecurityPolicy.class); final PolicyDescription policyDesc = new PolicyDescription(); final String policyName = policy.PolicyName; final String policyTypeName = policy.PolicyTypeName; if(policyName == null || policyTypeName==null) throw new Exception("PolicyName and PolicyTypeName must not be null"); policyDesc.setPolicyName(policyName); policyDesc.setPolicyTypeName(policyTypeName); final List<PolicyAttributeDescription> policyAttrs = Lists.newArrayList(Iterables.filter( Lists.transform(policy.PolicyAttributeDescriptions, new Function<AttributeNameValuePair, PolicyAttributeDescription>(){ @Override public PolicyAttributeDescription apply(AttributeNameValuePair arg0) { if(arg0.AttributeName==null || arg0.AttributeValue==null) return null; final PolicyAttributeDescription attr = new PolicyAttributeDescription(); attr.setAttributeName(arg0.AttributeName); attr.setAttributeValue(arg0.AttributeValue); return attr; } }), Predicates.notNull())); final PolicyAttributeDescriptions descs = new PolicyAttributeDescriptions(); descs.setMember((ArrayList<PolicyAttributeDescription>) policyAttrs); policyDesc.setPolicyAttributeDescriptions(descs); return policyDesc; }catch(final Exception ex){ LOG.warn(String.format("Unable to read ELB security policy file: %s", pathToAttributeJson), ex); return null; } } private static List<PolicyDescription> samplePolicyDescription = Lists.newArrayList(); private static List<PolicyDescription> getSamplePolicyDescription42(){ if(samplePolicyDescription.isEmpty()){ samplePolicyDescription = getSamplePolicyDescription40(); PolicyDescription policyDesc = null; String[] policyFiles = null; final Set<String> policyNames = Sets.newHashSet(); final String dir = String.format("%s/elb-security-policy", BaseDirectory.CONF); try{ final File policyDirectory = new File(dir); policyFiles = policyDirectory.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { if(name!=null && name.toLowerCase().endsWith(".json")) return true; else return false; }}); if(policyFiles == null) throw new Exception("The directory '"+dir+"' is not found"); }catch(final Exception ex) { LOG.error("Failed to find ELB security policy files", ex); } Date latest = new Date(Long.MIN_VALUE); for(final String policyFileName : policyFiles) { final String policyFilePath = String.format("%s/%s", dir, policyFileName); if ((policyDesc = getPolicyDescription(policyFilePath))!=null) { if(!policyNames.contains(policyDesc.getPolicyName())) { samplePolicyDescription.add(policyDesc); policyNames.add(policyDesc.getPolicyName()); try{ final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM"); final Date policyDate = df.parse(policyDesc.getPolicyName().substring(policyDesc.getPolicyName().length()-7)); if (policyDate.after(latest)) { latest = policyDate; LATEST_SECURITY_POLICY_NAME = policyDesc.getPolicyName(); } }catch(final Exception ex){ ; } } else { LOG.warn("Policy with dupilcate policy name found: "+ policyDesc.getPolicyName()); } } } } return samplePolicyDescription; } private static List<PolicyDescription> getSamplePolicyDescription40(){ final List<PolicyDescription> sampleList = Lists.newArrayList(); final PolicyDescription appCookieStick = new PolicyDescription(); appCookieStick.setPolicyName("ELBSample-AppCookieStickinessPolicy"); appCookieStick.setPolicyTypeName("AppCookieStickinessPolicyType"); final PolicyAttributeDescription appCookieAttr = new PolicyAttributeDescription(); appCookieAttr.setAttributeName("CookieName"); appCookieAttr.setAttributeValue("ELBSampleCookie"); final PolicyAttributeDescriptions appCookieAttrs = new PolicyAttributeDescriptions(); appCookieAttrs.setMember(Lists.newArrayList(appCookieAttr)); appCookieStick.setPolicyAttributeDescriptions(appCookieAttrs); sampleList.add(appCookieStick); final PolicyDescription lbCookieStick = new PolicyDescription(); lbCookieStick.setPolicyName("ELBSample-LBCookieStickinessPolicy"); lbCookieStick.setPolicyTypeName("LBCookieStickinessPolicyType"); final PolicyAttributeDescription lbCookieAttr = new PolicyAttributeDescription(); lbCookieAttr.setAttributeName("CookieExpirationPeriod"); lbCookieAttr.setAttributeValue("100"); final PolicyAttributeDescriptions lbCookieAttrs = new PolicyAttributeDescriptions(); lbCookieAttrs.setMember(Lists.newArrayList(lbCookieAttr)); lbCookieStick.setPolicyAttributeDescriptions(lbCookieAttrs); sampleList.add(lbCookieStick); return sampleList; } public enum AsPolicyDescription implements Function<LoadBalancerPolicyDescription, PolicyDescription> { INSTANCE; @Override public PolicyDescription apply(LoadBalancerPolicyDescription arg0) { if(arg0==null) return null; final PolicyDescription policy = new PolicyDescription(); policy.setPolicyName(arg0.getPolicyName()); policy.setPolicyTypeName(arg0.getPolicyTypeName()); final List<PolicyAttributeDescription> attrDescs = Lists.newArrayList(); for(final LoadBalancerPolicyAttributeDescriptionCoreView descView : arg0.getPolicyAttributeDescription()){ final PolicyAttributeDescription desc = new PolicyAttributeDescription(); desc.setAttributeName(descView.getAttributeName()); desc.setAttributeValue(descView.getAttributeValue()); attrDescs.add(desc); } final PolicyAttributeDescriptions descs = new PolicyAttributeDescriptions(); descs.setMember((ArrayList<PolicyAttributeDescription>) attrDescs); policy.setPolicyAttributeDescriptions(descs); return policy; } } public enum AsPolicyTypeDescription implements Function<LoadBalancerPolicyTypeDescription, PolicyTypeDescription>{ INSTANCE; @Override public PolicyTypeDescription apply(LoadBalancerPolicyTypeDescription arg0) { if(arg0 == null) return null; final PolicyTypeDescription policyType = new PolicyTypeDescription(); policyType.setPolicyTypeName(arg0.getPolicyTypeName()); policyType.setDescription(arg0.getDescription()); final List<LoadBalancerPolicyAttributeTypeDescriptionCoreView> policyAttributeTypeDesc = arg0.getPolicyAttributeTypeDescriptions(); if(policyAttributeTypeDesc != null && policyAttributeTypeDesc.size()>0){ final List<PolicyAttributeTypeDescription> attrTypes = Lists.newArrayList(); for(final LoadBalancerPolicyAttributeTypeDescriptionCoreView from : policyAttributeTypeDesc){ final PolicyAttributeTypeDescription to = new PolicyAttributeTypeDescription(); to.setAttributeName(from.getAttributeName()); to.setAttributeType(from.getAttributeType()); to.setCardinality(from.getCardinality()); to.setDefaultValue(from.getDefaultValue()); to.setDescription(from.getDescription()); attrTypes.add(to); } final PolicyAttributeTypeDescriptions attrDescs = new PolicyAttributeTypeDescriptions(); attrDescs.setMember((ArrayList<PolicyAttributeTypeDescription>) attrTypes); policyType.setPolicyAttributeTypeDescriptions(attrDescs); } return policyType; } } }