All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dasein.cloud.cloudstack.network.SecurityGroup Maven / Gradle / Ivy

Go to download

Implements the Dasein Cloud API for Cloud.com Cloudstack-based public and private clouds.

There is a newer version: 2015.10.5
Show newest version
/**
 * Copyright (C) 2009-2015 Dell, Inc.
 *
 * ====================================================================
 * Licensed 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.dasein.cloud.cloudstack.network;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.OperationNotSupportedException;
import org.dasein.cloud.ResourceStatus;
import org.dasein.cloud.Tag;
import org.dasein.cloud.cloudstack.CSCloud;
import org.dasein.cloud.cloudstack.CSException;
import org.dasein.cloud.cloudstack.CSMethod;
import org.dasein.cloud.cloudstack.Param;
import org.dasein.cloud.network.AbstractFirewallSupport;
import org.dasein.cloud.network.Direction;
import org.dasein.cloud.network.Firewall;
import org.dasein.cloud.network.FirewallCapabilities;
import org.dasein.cloud.network.FirewallCreateOptions;
import org.dasein.cloud.network.FirewallRule;
import org.dasein.cloud.network.FirewallRuleCreateOptions;
import org.dasein.cloud.network.Permission;
import org.dasein.cloud.network.Protocol;
import org.dasein.cloud.network.RuleTarget;
import org.dasein.cloud.network.RuleTargetType;
import org.dasein.cloud.util.APITrace;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class SecurityGroup extends AbstractFirewallSupport {
    static private final Logger logger = Logger.getLogger(SecurityGroup.class);

    static public final String AUTHORIZE_SECURITY_GROUP_EGRESS  = "authorizeSecurityGroupEgress";
    static public final String AUTHORIZE_SECURITY_GROUP_INGRESS = "authorizeSecurityGroupIngress";
    static public final String CREATE_SECURITY_GROUP            = "createSecurityGroup";
    static public final String DELETE_SECURITY_GROUP            = "deleteSecurityGroup";
    static public final String LIST_SECURITY_GROUPS             = "listSecurityGroups";
    static public final String REVOKE_SECURITY_GROUP_EGRESS     = "revokeSecurityGroupEgress";
    static public final String REVOKE_SECURITY_GROUP_INGRESS    = "revokeSecurityGroupIngress";

    SecurityGroup(CSCloud provider) {
        super(provider);
    }

    @Override
    public @Nonnull String authorize(@Nonnull String firewallId, @Nonnull Direction direction, @Nonnull Permission permission, @Nonnull RuleTarget sourceEndpoint, @Nonnull Protocol protocol, @Nonnull RuleTarget destinationEndpoint, int beginPort, int endPort, @Nonnegative int precedence) throws CloudException, InternalException {
        APITrace.begin(getProvider(), "Firewall.authorize");
        try {
            if( !permission.equals(Permission.ALLOW) ) {
                throw new OperationNotSupportedException("Only ALLOW rules are supported");
            }
            String sourceCidr = null;
            boolean group;
            String command = AUTHORIZE_SECURITY_GROUP_EGRESS;

            if( direction.equals(Direction.INGRESS) ) {
                command = AUTHORIZE_SECURITY_GROUP_INGRESS;
                group = sourceEndpoint.getRuleTargetType().equals(RuleTargetType.GLOBAL);
                if( !group ) {
                    sourceCidr = sourceEndpoint.getCidr();
                }
            }
            else {
                group = destinationEndpoint.getRuleTargetType().equals(RuleTargetType.GLOBAL);
                if( !group ) {
                    sourceCidr = destinationEndpoint.getCidr();
                }
            }
            // TODO should be communicated via capabilities
            if( group ) {
                throw new OperationNotSupportedException("Security group sources & destinations are not supported");
            }
            if( sourceCidr != null && sourceCidr.indexOf('/') == -1 ) {
                sourceCidr = sourceCidr + "/32";
            }
            Document doc = new CSMethod(getProvider()).get(
                    command,
                    new Param("securitygroupid", firewallId),
                    new Param("cidrlist", sourceCidr),
                    new Param(Protocol.ICMP.equals(protocol) ? "icmptype" : "startport", String.valueOf(beginPort)),
                    new Param(Protocol.ICMP.equals(protocol) ? "icmpcode" : "endport", String.valueOf(endPort)),
                    new Param("protocol", protocol.name())
            );
            getProvider().waitForJob(doc, "Authorize rule");
            final String id = getRuleId(firewallId, direction, permission, protocol, sourceEndpoint, destinationEndpoint, beginPort, endPort);
            if( id == null ) {
                throw new CloudException("Unable to identify newly created firewall rule ID");
            }
            return id;
        }
        finally {
            APITrace.end();
        }
    }

    private @Nullable String getRuleId(@Nonnull String firewallId, @Nonnull Direction direction, @Nonnull Permission permission, @Nonnull Protocol protocol, @Nonnull RuleTarget sourceEndpoint, @Nonnull RuleTarget destinationEndpoint, int beginPort, int endPort) throws CloudException, InternalException {

        //
        // 720e3652-49f9-4d45-a426-fbf55d3c10e0
        // tcp
        // 83
        // 83
        // 209.98.98.98/32
        // 
        for( FirewallRule rule : getRules(firewallId) ) {
            if( rule.getDirection().equals(direction) ) {
                if( rule.getPermission().equals(permission) ) {
                    if( rule.getProtocol().equals(protocol) ) {
                        if( rule.getSourceEndpoint().getRuleTargetType().equals(sourceEndpoint.getRuleTargetType()) ) {
                            if( rule.getDestinationEndpoint().getRuleTargetType().equals(destinationEndpoint.getRuleTargetType()) ) {
                                if( rule.getStartPort() == beginPort ) {
                                    if( rule.getEndPort() == endPort ) {
                                        if( rule.getSourceEndpoint().getRuleTargetType().equals(RuleTargetType.CIDR) ) {
                                            //noinspection ConstantConditions
                                            if( rule.getSourceEndpoint().getCidr().equals(sourceEndpoint.getCidr()) ) {
                                                if( rule.getDestinationEndpoint().getRuleTargetType().equals(RuleTargetType.CIDR) ) {
                                                    //noinspection ConstantConditions
                                                    if( rule.getDestinationEndpoint().getCidr().equals(destinationEndpoint.getCidr()) ) {
                                                        return rule.getProviderRuleId();
                                                    }
                                                }
                                                else if( rule.getDestinationEndpoint().getRuleTargetType().equals(RuleTargetType.GLOBAL) ) {
                                                    //noinspection ConstantConditions
                                                    if( rule.getDestinationEndpoint().getProviderFirewallId().equals(destinationEndpoint.getProviderFirewallId()) ) {
                                                        return rule.getProviderRuleId();
                                                    }
                                                }
                                            }
                                        }
                                        else if( rule.getSourceEndpoint().getRuleTargetType().equals(RuleTargetType.GLOBAL) ) {
                                            //noinspection ConstantConditions
                                            if( rule.getSourceEndpoint().getProviderFirewallId().equals(sourceEndpoint.getProviderFirewallId()) ) {
                                                return rule.getProviderRuleId();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    @Override
    public @Nonnull String create(@Nonnull FirewallCreateOptions options) throws InternalException, CloudException {
        if( options.getProviderVlanId() != null ) {
            throw new OperationNotSupportedException("No VLAN security groups are supported");
        }
        APITrace.begin(getProvider(), "Firewall.create");
        try {
            final Document doc = new CSMethod(getProvider()).get(
                    CREATE_SECURITY_GROUP,
                    new Param("name", options.getName()),
                    new Param("description", options.getDescription())
            );
            final NodeList matches = doc.getElementsByTagName("id");
            String groupId = null;

            if( matches.getLength() > 0 ) {
                groupId = matches.item(0).getFirstChild().getNodeValue();
            }
            if( groupId == null ) {
                throw new CloudException("Failed to create firewall");
            }

            // create initial rules if requested
            for( FirewallRuleCreateOptions ruleCreateOptions : options.getInitialRules() ) {
                authorize(groupId, ruleCreateOptions);
            }

            // Set tags
            List tags = new ArrayList();
            Map meta = options.getMetaData();
            for( Entry entry : meta.entrySet() ) {
            	if( entry.getKey().equalsIgnoreCase("name") || entry.getKey().equalsIgnoreCase("description") ) {
            		continue;
            	}
            	if (entry.getValue() != null && !entry.getValue().equals("")) {
            		tags.add(new Tag(entry.getKey(), entry.getValue()));
            	}
            }
            tags.add(new Tag("Name", options.getName()));
            tags.add(new Tag("Description", options.getDescription()));
            getProvider().createTags(new String[] { groupId }, "SecurityGroup", tags.toArray(new Tag[tags.size()]));
            return groupId;
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public void delete(@Nonnull String firewallId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "Firewall.delete");
        try {
            try {
                for( FirewallRule rule : getRules(firewallId) ) {
                    try { revoke(rule.getProviderRuleId()); }
                    catch( Throwable ignore ) { }
                }
            }
            catch( Throwable ignore ) {
                // ignore
            }
            new CSMethod(getProvider()).get(DELETE_SECURITY_GROUP, new Param("id", firewallId));
        }
        finally {
            APITrace.end();
        }
    }

    private transient volatile SecurityGroupCapabilities capabilities;

    @Nonnull
    @Override
    public FirewallCapabilities getCapabilities() throws CloudException, InternalException {
        if( capabilities == null ) {
            capabilities = new SecurityGroupCapabilities(getProvider());
        }
        return capabilities;
    }

    @Override
    public @Nullable Firewall getFirewall(@Nonnull String firewallId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "Firewall.getFirewall");
        try {
            final Document doc = new CSMethod(getProvider()).get(LIST_SECURITY_GROUPS, new Param("id", firewallId));
            final NodeList matches = doc.getElementsByTagName("securitygroup");

            for( int i=0; i getRules(@Nonnull String firewallId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "Firewall.getRules");
        try {
            final CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(LIST_SECURITY_GROUPS, new Param("id", firewallId));
            final List rules = new ArrayList();

            int numPages = 1;
            NodeList nodes = doc.getElementsByTagName("count");
            Node n = nodes.item(0);
            if (n != null) {
                String value = n.getFirstChild().getNodeValue().trim();
                int count = Integer.parseInt(value);
                numPages = count/500;
                int remainder = count % 500;
                if (remainder > 0) {
                    numPages++;
                }
            }

            for (int page = 1; page <= numPages; page++) {
                if (page > 1) {
                    String nextPage = String.valueOf(page);
                    doc = method.get(LIST_SECURITY_GROUPS, new Param("id", firewallId), new Param("pagesize", "500"), new Param("page", nextPage));
                }
                NodeList matches = doc.getElementsByTagName("ingressrule");
                for( int i=0; i list() throws InternalException, CloudException {
        APITrace.begin(getProvider(), "Firewall.list");
        try {
            CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(LIST_SECURITY_GROUPS);
            final List firewalls = new ArrayList();

            int numPages = 1;
            NodeList nodes = doc.getElementsByTagName("count");
            Node n = nodes.item(0);
            if (n != null) {
                String value = n.getFirstChild().getNodeValue().trim();
                int count = Integer.parseInt(value);
                numPages = count/500;
                int remainder = count % 500;
                if (remainder > 0) {
                    numPages++;
                }
            }

            for (int page = 1; page <= numPages; page++) {
                if (page > 1) {
                    String nextPage = String.valueOf(page);
                    doc = method.get(LIST_SECURITY_GROUPS, new Param("pagesize", "500"), new Param("page", nextPage));
                }
                NodeList matches = doc.getElementsByTagName("securitygroup");

                for( int i=0; i listFirewallStatus() throws InternalException, CloudException {
        APITrace.begin(getProvider(), "Firewall.listFirewallStatus");
        try {
            final CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(LIST_SECURITY_GROUPS);
            final List firewalls = new ArrayList();

            int numPages = 1;
            NodeList nodes = doc.getElementsByTagName("count");
            Node n = nodes.item(0);
            if (n != null) {
                String value = n.getFirstChild().getNodeValue().trim();
                int count = Integer.parseInt(value);
                numPages = count/500;
                int remainder = count % 500;
                if (remainder > 0) {
                    numPages++;
                }
            }

            for (int page = 1; page <= numPages; page++) {
                if (page > 1) {
                    String nextPage = String.valueOf(page);
                    doc = method.get(LIST_SECURITY_GROUPS, new Param("pagesize", "500"), new Param("page", nextPage));
                }
                NodeList matches = doc.getElementsByTagName("securitygroup");

                for( int i=0; i listFirewallsForVM(@Nonnull String vmId) throws CloudException, InternalException {
        APITrace.begin(getProvider(), "Firewall.listFirewallsForVM");
        try {
            final CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(LIST_SECURITY_GROUPS, new Param("virtualmachineId", vmId));
            final List firewalls = new ArrayList();

            int numPages = 1;
            NodeList nodes = doc.getElementsByTagName("count");
            Node n = nodes.item(0);
            if (n != null) {
                String value = n.getFirstChild().getNodeValue().trim();
                int count = Integer.parseInt(value);
                numPages = count/500;
                int remainder = count % 500;
                if (remainder > 0) {
                    numPages++;
                }
            }

            for (int page = 1; page <= numPages; page++) {
                if (page > 1) {
                    String nextPage = String.valueOf(page);
                    doc = method.get(LIST_SECURITY_GROUPS,
                            new Param("virtualmachineId", vmId),
                            new Param("pagesize", "500"),
                            new Param("page", nextPage)
                    );
                }
                NodeList matches = doc.getElementsByTagName("securitygroup");

                for( int i=0; i 0 ) {
                value = attribute.getFirstChild().getNodeValue();                
            }
            else {
                value = null;
            }
            if( name.equalsIgnoreCase("id") && value != null ) {
                firewall.setProviderFirewallId(value);
            }
            else if( name.equalsIgnoreCase("description") && value != null ) {
                firewall.setDescription(value);
            }
            else if( name.equalsIgnoreCase("name") && value != null ) {
                firewall.setName(value);
            }
        }
        if( firewall.getProviderFirewallId() == null ) {
            logger.warn("Discovered firewall " + firewall.getProviderFirewallId() + " with an empty firewall ID");
            return null;
        }
        String id = firewall.getProviderFirewallId();
        String name;

        if( id == null ) {
            return null;
        }
        name = firewall.getName();
        if( name == null ) {
            name = id;
            firewall.setName(name);
        }
        if( firewall.getDescription() == null ) {
            firewall.setDescription(name);
        }
        return firewall;
    }
    
    private FirewallRule toRule(String firewallId, Node node, Direction direction) {
        if( node == null) {
            return null;
        }
        
        NodeList attributes = node.getChildNodes();
        int startPort = -1, endPort = -1;
        Protocol protocol = Protocol.TCP;
        String source = "0.0.0.0/0";
        String ruleId = null;

        for( int i=0; i 0 ) {
                value = attribute.getFirstChild().getNodeValue();                
            }
            else {
                value = null;
            }
            if( name.equalsIgnoreCase("cidr") && value != null ) {
                source = value;
            }
            else if( name.equalsIgnoreCase("endport") && value != null ) {
                endPort = Integer.parseInt(value);
            }
            else if( name.equalsIgnoreCase("startport") && value != null ) {
                startPort = Integer.parseInt(value);
            }
            else if( name.equalsIgnoreCase("protocol") && value != null ) {
                protocol = Protocol.valueOf(value.toUpperCase());
            }
            else if( name.equalsIgnoreCase("ruleId") && value != null ) {
                ruleId = value;
            }
        }
        if( (startPort == -1 || endPort == -1) && (startPort != -1 || endPort != -1) ) {
            if( startPort == -1 ) {
                startPort = endPort;
            }
            else {
                endPort = startPort;
            }
        }
        if( direction.equals(Direction.INGRESS) ) {
            return FirewallRule.getInstance(ruleId, firewallId, RuleTarget.getCIDR(source), direction, protocol, Permission.ALLOW, RuleTarget.getGlobal(firewallId), startPort, endPort);
        }
        else {
            return FirewallRule.getInstance(ruleId, firewallId, RuleTarget.getGlobal(firewallId), direction, protocol, Permission.ALLOW, RuleTarget.getCIDR(source), startPort, endPort);
        }
    }

    private @Nullable ResourceStatus toStatus(@Nullable Node node) {
        if( node == null ) {
            return null;
        }
        NodeList attributes = node.getChildNodes();

        for( int i=0; i 0 ) {
                value = attribute.getFirstChild().getNodeValue();
            }
            else {
                value = null;
            }
            if( name.equalsIgnoreCase("id") && value != null ) {
                return new ResourceStatus(value, true);
            }
        }
        return null;
    }
    
	@Override
	public void setTags(@Nonnull String firewallId, @Nonnull Tag... tags) throws CloudException, InternalException {
		setTags(new String[] { firewallId }, tags);
	}

	@Override
	public void setTags(@Nonnull String[] firewallIds, @Nonnull Tag... tags) throws CloudException, InternalException {
		APITrace.begin(getProvider(), "Firewall.setTags");
		try {
			removeTags(firewallIds);
			getProvider().createTags(firewallIds, "SecurityGroup", tags);
		}
		finally {
			APITrace.end();
		}
	}

	@Override
	public void updateTags(@Nonnull String firewallId, @Nonnull Tag... tags) throws CloudException, InternalException {
		updateTags(new String[] { firewallId }, tags);
	}

	@Override
	public void updateTags(@Nonnull String[] firewallIds, @Nonnull Tag... tags) throws CloudException, InternalException {
		APITrace.begin(getProvider(), "Firewall.updateTags");
		try {
			getProvider().updateTags(firewallIds, "SecurityGroup", tags);
		} 
		finally {
			APITrace.end();
		}
	}

	@Override
	public void removeTags(@Nonnull String firewallId, @Nonnull Tag... tags) throws CloudException, InternalException {
		removeTags(new String[] { firewallId }, tags);
	}

	@Override
	public void removeTags(@Nonnull String[] firewallIds, @Nonnull Tag... tags) throws CloudException, InternalException {
		APITrace.begin(getProvider(), "Firewall.removeTags");
		try {
			getProvider().removeTags(firewallIds, "SecurityGroup", tags);
		}
		finally {
			APITrace.end();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy