diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 966b7c4227b..a05310bff77 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -549,10 +549,6 @@ listSrxFirewalls=1 listSrxFirewallNetworks=1 #### Palo Alto firewall commands -addExternalFirewall=1 -deleteExternalFirewall=1 -listExternalFirewalls=1 - addPaloAltoFirewall=1 deletePaloAltoFirewall=1 configurePaloAltoFirewall=1 diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java deleted file mode 100644 index 2e4d6717181..00000000000 --- a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java +++ /dev/null @@ -1,115 +0,0 @@ -// 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.api.commands; - -import javax.inject.Inject; - -import org.apache.log4j.Logger; - -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.ExternalFirewallResponse; -import org.apache.cloudstack.api.response.ZoneResponse; - -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.host.Host; -import com.cloud.network.element.PaloAltoFirewallElementService; -import com.cloud.user.Account; -import com.cloud.utils.exception.CloudRuntimeException; - -@APICommand(name = "addExternalFirewall", description = "Adds an external firewall appliance", responseObject = ExternalFirewallResponse.class) -public class AddExternalFirewallCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddExternalFirewallCmd.class.getName()); - private static final String s_name = "addexternalfirewallresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - @Parameter(name = ApiConstants.ZONE_ID, - type = CommandType.UUID, - entityType = ZoneResponse.class, - required = true, - description = "Zone in which to add the external firewall appliance.") - private Long zoneId; - - @Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "URL of the external firewall appliance.") - private String url; - - @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = true, description = "Username of the external firewall appliance.") - private String username; - - @Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, required = true, description = "Password of the external firewall appliance.") - private String password; - - /////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getZoneId() { - return zoneId; - } - - public String getUrl() { - return url; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Inject - PaloAltoFirewallElementService _paElementService; - - @Override - public String getCommandName() { - return s_name; - } - - @Override - public long getEntityOwnerId() { - return Account.ACCOUNT_ID_SYSTEM; - } - - @SuppressWarnings("deprecation") - @Override - public void execute() { - try { - Host externalFirewall = _paElementService.addExternalFirewall(this); - ExternalFirewallResponse response = _paElementService.createExternalFirewallResponse(externalFirewall); - response.setObjectName("externalfirewall"); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } catch (InvalidParameterValueException ipve) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ipve.getMessage()); - } catch (CloudRuntimeException cre) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, cre.getMessage()); - } - } -} diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java deleted file mode 100644 index 7a3cec8824b..00000000000 --- a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java +++ /dev/null @@ -1,89 +0,0 @@ -// 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.api.commands; - -import javax.inject.Inject; - -import org.apache.log4j.Logger; - -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.HostResponse; -import org.apache.cloudstack.api.response.SuccessResponse; - -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.element.PaloAltoFirewallElementService; -import com.cloud.user.Account; - -@APICommand(name = "deleteExternalFirewall", description = "Deletes an external firewall appliance.", responseObject = SuccessResponse.class) -public class DeleteExternalFirewallCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteExternalFirewallCmd.class.getName()); - private static final String s_name = "deleteexternalfirewallresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = HostResponse.class, required = true, description = "Id of the external firewall appliance.") - private Long id; - - /////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getId() { - return id; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Inject - PaloAltoFirewallElementService _paElementService; - - @Override - public String getCommandName() { - return s_name; - } - - @Override - public long getEntityOwnerId() { - return Account.ACCOUNT_ID_SYSTEM; - } - - @SuppressWarnings("deprecation") - @Override - public void execute() { - try { - boolean result = _paElementService.deleteExternalFirewall(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete external firewall."); - } - } catch (InvalidParameterValueException e) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Failed to delete external firewall."); - } - } -} diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java deleted file mode 100644 index 6c661def803..00000000000 --- a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java +++ /dev/null @@ -1,89 +0,0 @@ -// 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.api.commands; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import org.apache.log4j.Logger; - -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseListCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; -import org.apache.cloudstack.api.response.ExternalFirewallResponse; -import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.ZoneResponse; - -import com.cloud.host.Host; -import com.cloud.network.element.PaloAltoFirewallElementService; - -@APICommand(name = "listExternalFirewalls", description = "List external firewall appliances.", responseObject = ExternalFirewallResponse.class) -public class ListExternalFirewallsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListServiceOfferingsCmd.class.getName()); - private static final String s_name = "listexternalfirewallsresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "zone Id") - private long zoneId; - - ///////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public long getZoneId() { - return zoneId; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Inject - PaloAltoFirewallElementService _paElementService; - - @Override - public String getCommandName() { - return s_name; - } - - @SuppressWarnings("deprecation") - @Override - public void execute() { - - List externalFirewalls = _paElementService.listExternalFirewalls(this); - - ListResponse listResponse = new ListResponse(); - List responses = new ArrayList(); - for (Host externalFirewall : externalFirewalls) { - ExternalFirewallResponse response = _paElementService.createExternalFirewallResponse(externalFirewall); - response.setObjectName("externalfirewall"); - response.setResponseName(getCommandName()); - responses.add(response); - } - - listResponse.setResponses(responses); - listResponse.setResponseName(getCommandName()); - this.setResponseObject(listResponse); - } -} diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java index a38ca713de3..be9a0b880fe 100644 --- a/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java +++ b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java @@ -32,12 +32,9 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; import com.cloud.api.ApiDBUtils; -import com.cloud.api.commands.AddExternalFirewallCmd; import com.cloud.api.commands.AddPaloAltoFirewallCmd; import com.cloud.api.commands.ConfigurePaloAltoFirewallCmd; -import com.cloud.api.commands.DeleteExternalFirewallCmd; import com.cloud.api.commands.DeletePaloAltoFirewallCmd; -import com.cloud.api.commands.ListExternalFirewallsCmd; import com.cloud.api.commands.ListPaloAltoFirewallNetworksCmd; import com.cloud.api.commands.ListPaloAltoFirewallsCmd; import com.cloud.api.response.PaloAltoFirewallResponse; @@ -293,85 +290,12 @@ public class PaloAltoExternalFirewallElement extends ExternalFirewallDeviceManag return true; } - @Override - @Deprecated - // should use more generic addNetworkDevice command to add firewall - public - Host addExternalFirewall(AddExternalFirewallCmd cmd) { - Long zoneId = cmd.getZoneId(); - DataCenterVO zone = null; - PhysicalNetworkVO pNetwork = null; - HostVO fwHost = null; - - zone = _dcDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); - } - - List physicalNetworks = _physicalNetworkDao.listByZone(zoneId); - if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) { - throw new InvalidParameterValueException("There are no physical networks or multiple physical networks configured in zone with ID: " + zoneId + - " to add this device."); - } - pNetwork = physicalNetworks.get(0); - - String deviceType = NetworkDevice.PaloAltoFirewall.getName(); - ExternalFirewallDeviceVO fwDeviceVO = - addExternalFirewall(pNetwork.getId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceType, new PaloAltoResource()); - if (fwDeviceVO != null) { - fwHost = _hostDao.findById(fwDeviceVO.getHostId()); - } - - return fwHost; - } - - @Override - public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd) { - return deleteExternalFirewall(cmd.getId()); - } - - @Override - @Deprecated - // should use more generic listNetworkDevice command - public - List listExternalFirewalls(ListExternalFirewallsCmd cmd) { - List firewallHosts = new ArrayList(); - Long zoneId = cmd.getZoneId(); - DataCenterVO zone = null; - PhysicalNetworkVO pNetwork = null; - - if (zoneId != null) { - zone = _dcDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); - } - - List physicalNetworks = _physicalNetworkDao.listByZone(zoneId); - if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) { - throw new InvalidParameterValueException("There are no physical networks or multiple physical networks configured in zone with ID: " + zoneId + - " to add this device."); - } - pNetwork = physicalNetworks.get(0); - } - - firewallHosts.addAll(listExternalFirewalls(pNetwork.getId(), NetworkDevice.PaloAltoFirewall.getName())); - return firewallHosts; - } - - @Override - public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall) { - return super.createExternalFirewallResponse(externalFirewall); - } - @Override public List> getCommands() { List> cmdList = new ArrayList>(); - cmdList.add(AddExternalFirewallCmd.class); cmdList.add(AddPaloAltoFirewallCmd.class); cmdList.add(ConfigurePaloAltoFirewallCmd.class); - cmdList.add(DeleteExternalFirewallCmd.class); cmdList.add(DeletePaloAltoFirewallCmd.class); - cmdList.add(ListExternalFirewallsCmd.class); cmdList.add(ListPaloAltoFirewallNetworksCmd.class); cmdList.add(ListPaloAltoFirewallsCmd.class); return cmdList; diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java index 17b3133b391..12f04077215 100644 --- a/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java +++ b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java @@ -20,12 +20,9 @@ import java.util.List; import org.apache.cloudstack.api.response.ExternalFirewallResponse; -import com.cloud.api.commands.AddExternalFirewallCmd; import com.cloud.api.commands.AddPaloAltoFirewallCmd; import com.cloud.api.commands.ConfigurePaloAltoFirewallCmd; -import com.cloud.api.commands.DeleteExternalFirewallCmd; import com.cloud.api.commands.DeletePaloAltoFirewallCmd; -import com.cloud.api.commands.ListExternalFirewallsCmd; import com.cloud.api.commands.ListPaloAltoFirewallNetworksCmd; import com.cloud.api.commands.ListPaloAltoFirewallsCmd; import com.cloud.api.response.PaloAltoFirewallResponse; @@ -72,24 +69,4 @@ public interface PaloAltoFirewallElementService extends PluggableService { public List listNetworks(ListPaloAltoFirewallNetworksCmd cmd); public PaloAltoFirewallResponse createPaloAltoFirewallResponse(ExternalFirewallDeviceVO fwDeviceVO); - - @Deprecated - // API helper function supported for backward compatibility - public - Host addExternalFirewall(AddExternalFirewallCmd cmd); - - @Deprecated - // API helper function supported for backward compatibility - public - boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd); - - @Deprecated - // API helper function supported for backward compatibility - public - List listExternalFirewalls(ListExternalFirewallsCmd cmd); - - @Deprecated - // API helper function supported for backward compatibility - public - ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall); } diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java b/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java index 2fac31efac5..1b05a116f33 100644 --- a/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java +++ b/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java @@ -29,6 +29,7 @@ import java.util.Map; import javax.naming.ConfigurationException; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.dom.DOMSource; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.Transformer; @@ -55,6 +56,7 @@ import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.log4j.Logger; import org.w3c.dom.Document; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; @@ -462,11 +464,14 @@ public class PaloAltoResource implements ServerResource { String guestVlanSubnet = NetUtils.getCidrSubNet(guestVlanGateway, cidrSize); Long publicVlanTag = null; - if (ip.getBroadcastUri() != null && !ip.getBroadcastUri().equals("untagged")) { - try { - publicVlanTag = Long.parseLong(ip.getBroadcastUri()); - } catch (Exception e) { - throw new ExecutionException("Could not parse public VLAN tag: " + ip.getBroadcastUri()); + if (ip.getBroadcastUri() != null) { + String parsedVlanTag = parsePublicVlanTag(ip.getBroadcastUri()); + if (!parsedVlanTag.equals("untagged")) { + try { + publicVlanTag = Long.parseLong(parsedVlanTag); + } catch (Exception e) { + throw new ExecutionException("Could not parse public VLAN tag: " + parsedVlanTag); + } } } @@ -520,6 +525,9 @@ public class PaloAltoResource implements ServerResource { String privateGateway, String privateSubnet, long privateCidrSize) throws ExecutionException { privateSubnet = privateSubnet + "/" + privateCidrSize; + // remove any orphaned egress rules if they exist... + removeOrphanedFirewallRules(cmdList, privateVlanTag); + if (type.equals(GuestNetworkType.SOURCE_NAT)) { manageNetworkIsolation(cmdList, PaloAltoPrimative.DELETE, privateVlanTag, privateSubnet, privateGateway); manageSrcNatRule(cmdList, PaloAltoPrimative.DELETE, type, publicVlanTag, sourceNatIpAddress + "/32", privateVlanTag, privateGateway + "/" + privateCidrSize); @@ -943,11 +951,16 @@ public class PaloAltoResource implements ServerResource { String dstNatName = genDstNatRuleName(publicIp, rule.getId()); String publicInterfaceName; - String publicVlanTag = rule.getSrcVlanTag(); - if (publicVlanTag == null || publicVlanTag.equals("untagged")) { + String publicVlanTag; + if (rule.getSrcVlanTag() == null) { publicInterfaceName = genPublicInterfaceName(new Long("9999")); } else { - publicInterfaceName = genPublicInterfaceName(new Long(publicVlanTag)); + publicVlanTag = parsePublicVlanTag(rule.getSrcVlanTag()); + if (publicVlanTag.equals("untagged")) { + publicInterfaceName = genPublicInterfaceName(new Long("9999")); + } else { + publicInterfaceName = genPublicInterfaceName(new Long(publicVlanTag)); + } } switch (prim) { @@ -1085,11 +1098,16 @@ public class PaloAltoResource implements ServerResource { String stcNatName = genStcNatRuleName(publicIp, rule.getId()); String publicInterfaceName; - String publicVlanTag = rule.getSrcVlanTag(); - if (publicVlanTag == null || publicVlanTag.equals("untagged")) { + String publicVlanTag; + if (rule.getSrcVlanTag() == null) { publicInterfaceName = genPublicInterfaceName(new Long("9999")); } else { - publicInterfaceName = genPublicInterfaceName(new Long(publicVlanTag)); + publicVlanTag = parsePublicVlanTag(rule.getSrcVlanTag()); + if (publicVlanTag.equals("untagged")) { + publicInterfaceName = genPublicInterfaceName(new Long("9999")); + } else { + publicInterfaceName = genPublicInterfaceName(new Long(publicVlanTag)); + } } switch (prim) { @@ -1170,13 +1188,20 @@ public class PaloAltoResource implements ServerResource { /* * Firewall rule implementation */ - - private String genFirewallRuleName(long id) { + private String genFirewallRuleName(long id) { // ingress return "policy_" + Long.toString(id); } + private String genFirewallRuleName(long id, String vlan) { // egress + return "policy_"+Long.toString(id)+"_"+vlan; + } public boolean manageFirewallRule(ArrayList cmdList, PaloAltoPrimative prim, FirewallRuleTO rule) throws ExecutionException { - String ruleName = genFirewallRuleName(rule.getId()); + String ruleName; + if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) { + ruleName = genFirewallRuleName(rule.getId(), rule.getSrcVlanTag()); + } else { + ruleName = genFirewallRuleName(rule.getId()); + } switch (prim) { @@ -1203,6 +1228,7 @@ public class PaloAltoResource implements ServerResource { String serviceXML; String protocol = rule.getProtocol(); + String action = "allow"; // Only ICMP will use an Application, so others will be any. if (protocol.equals(Protocol.ICMP.toString())) { @@ -1232,11 +1258,23 @@ public class PaloAltoResource implements ServerResource { serviceXML = "any"; } - if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) { // Network egress rule + // handle different types of fire wall rules (egress | ingress) + if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) { // Egress Rule srcZone = _privateZone; dstZone = _publicZone; dstAddressXML = "any"; - } else { + + // defaults to 'allow', the deny rules are as follows + if (rule.getType() == FirewallRule.FirewallRuleType.System) { + if (!rule.isDefaultEgressPolicy()) { // default of deny && system rule, so deny + action = "deny"; + } + } else { + if (rule.isDefaultEgressPolicy()) { // default is allow && user rule, so deny + action = "deny"; + } + } + } else { // Ingress Rule srcZone = _publicZone; dstZone = _privateZone; dstAddressXML = "" + rule.getSrcIp() + ""; @@ -1265,6 +1303,7 @@ public class PaloAltoResource implements ServerResource { } } + // build new rule xml String xml = ""; xml += "" + srcZone + ""; xml += "" + dstZone + ""; @@ -1272,16 +1311,52 @@ public class PaloAltoResource implements ServerResource { xml += "" + dstAddressXML + ""; xml += "" + appXML + ""; xml += "" + serviceXML + ""; - xml += "allow"; + xml += ""+action+""; xml += "no"; xml += "no"; - if (_threatProfile != null) { // add the threat profile if it exists + if (_threatProfile != null && action.equals("allow")) { // add the threat profile if it exists xml += "" + _threatProfile + ""; } - if (_logProfile != null) { // add the log profile if it exists + if (_logProfile != null && action.equals("allow")) { // add the log profile if it exists xml += "" + _logProfile + ""; } + boolean has_default = false; + String defaultEgressRule = ""; + if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) { + // check if a default egress rule exists because it always has to be after the other rules. + Map e_params = new HashMap(); + e_params.put("type", "config"); + e_params.put("action", "get"); + e_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0_"+rule.getSrcVlanTag()+"']"); + String e_response = request(PaloAltoMethod.GET, e_params); + has_default = (validResponse(e_response) && responseNotEmpty(e_response)); + + // there is an existing default rule, so we need to remove it and add it back after the new rule is added. + if (has_default) { + s_logger.debug("Moving the default egress rule after the new rule: "+ruleName); + NodeList response_body; + Document doc = getDocument(e_response); + XPath xpath = XPathFactory.newInstance().newXPath(); + try { + XPathExpression expr = xpath.compile("/response[@status='success']/result/entry/node()"); + response_body = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); + } catch (XPathExpressionException e) { + throw new ExecutionException(e.getCause().getMessage()); + } + for (int i=0; i dd_params = new HashMap(); + dd_params.put("type", "config"); + dd_params.put("action", "delete"); + dd_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0_"+rule.getSrcVlanTag()+"']"); + cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, dd_params)); + } + } + + // add the new rule... Map a_params = new HashMap(); a_params.put("type", "config"); a_params.put("action", "set"); @@ -1289,6 +1364,17 @@ public class PaloAltoResource implements ServerResource { a_params.put("element", xml); cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, a_params)); + // add back the default rule + if (rule.getTrafficType() == FirewallRule.TrafficType.Egress && has_default) { + Map da_params = new HashMap(); + da_params.put("type", "config"); + da_params.put("action", "set"); + da_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0_"+rule.getSrcVlanTag()+"']"); + da_params.put("element", defaultEgressRule); + cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, da_params)); + s_logger.debug("Completed move of the default egress rule after rule: "+ruleName); + } + return true; case DELETE: @@ -1310,6 +1396,25 @@ public class PaloAltoResource implements ServerResource { } } + // remove orphaned rules if they exist... + public void removeOrphanedFirewallRules(ArrayList cmdList, long vlan) throws ExecutionException { + Map params = new HashMap(); + params.put("type", "config"); + params.put("action", "get"); + params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[contains(@name, 'policy') and contains(@name, '"+Long.toString(vlan)+"')]"); + String response = request(PaloAltoMethod.GET, params); + boolean has_orphans = (validResponse(response) && responseNotEmpty(response)); + + if (has_orphans) { + Map d_params = new HashMap(); + d_params.put("type", "config"); + d_params.put("action", "delete"); + d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[contains(@name, 'policy') and contains(@name, '"+Long.toString(vlan)+"')]"); + cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, d_params)); + } + } + + /* * Usage */ @@ -1935,6 +2040,10 @@ public class PaloAltoResource implements ServerResource { return ip.replace('.', '-').replace('/', '-'); } + private String parsePublicVlanTag(String uri) { + return uri.replace("vlan://", ""); + } + private Protocol getProtocol(String protocolName) throws ExecutionException { protocolName = protocolName.toLowerCase(); @@ -1964,6 +2073,20 @@ public class PaloAltoResource implements ServerResource { } } + // return an xml node as a string + private String nodeToString(Node node) throws ExecutionException { + StringWriter sw = new StringWriter(); + try { + Transformer t = TransformerFactory.newInstance().newTransformer(); + t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + t.transform(new DOMSource(node), new StreamResult(sw)); + } catch (Throwable t) { + throw new ExecutionException("XML convert error when modifying PA config: "+t.getMessage()); + } + return sw.toString(); + } + + // pretty printing of xml strings private String prettyFormat(String input) { int indent = 4; try { @@ -1999,14 +2122,12 @@ public class PaloAltoResource implements ServerResource { @Override public void setName(String name) { // TODO Auto-generated method stub - } //@Override @Override public void setConfigParams(Map params) { // TODO Auto-generated method stub - } //@Override @@ -2027,7 +2148,5 @@ public class PaloAltoResource implements ServerResource { @Override public void setRunLevel(int level) { // TODO Auto-generated method stub - } - } diff --git a/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java b/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java index 3b70bd61776..44cc65bfcd8 100755 --- a/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java +++ b/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java @@ -161,12 +161,12 @@ public class MockablePaloAltoResource extends PaloAltoResource { } } - // get egress firewall rule | has_egress_fw_rule | policy_0 - if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0']")) { + // get egress firewall rule | has_egress_fw_rule | policy_0_3954 + if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0_3954']")) { if (context.containsKey("has_egress_fw_rule") && context.get("has_egress_fw_rule").equals("true")) { - response = + response = "" - + "" + + "" + "trustuntrust10.3.96.1/20" + "anyanycs_tcp_80" + "allownono"; @@ -190,6 +190,11 @@ public class MockablePaloAltoResource extends PaloAltoResource { } } + // get default egress rule | policy_0_3954 + if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[contains(@name, 'policy') and contains(@name, '3954')]")) { + response = ""; + } + // get destination nat rule (port forwarding) | has_dst_nat_rule if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='dst_nat.192-168-80-103_9']")) { if (context.containsKey("has_dst_nat_rule") && context.get("has_dst_nat_rule").equals("true")) { @@ -292,7 +297,7 @@ public class MockablePaloAltoResource extends PaloAltoResource { } // add egress firewall rule - if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0']")) { + if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0_3954']")) { response = "command succeeded"; context.put("has_egress_fw_rule", "true"); } @@ -325,7 +330,7 @@ public class MockablePaloAltoResource extends PaloAltoResource { // action = 'delete' if (params.get("action").equals("delete")) { // remove egress firewall rule - if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0']")) { + if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0_3954']")) { response = "command succeeded"; context.remove("has_egress_fw_rule"); } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index a2c0204438c..c345795fe37 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -3718,9 +3718,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Set firewallProviderSet = new HashSet(); firewallProviderSet.add(firewallProvider); serviceProviderMap.put(Service.Firewall, firewallProviderSet); - if (!(firewallProvider.getName().equals(Provider.JuniperSRX.getName()) || firewallProvider.getName().equals(Provider.VirtualRouter.getName())) && + if (!(firewallProvider.getName().equals(Provider.JuniperSRX.getName()) || firewallProvider.getName().equals(Provider.PaloAlto.getName()) || firewallProvider.getName().equals(Provider.VirtualRouter.getName())) && egressDefaultPolicy == false) { - throw new InvalidParameterValueException("Firewall egress with default policy " + egressDefaultPolicy + "is not supported by the provider " + + throw new InvalidParameterValueException("Firewall egress with default policy " + egressDefaultPolicy + " is not supported by the provider " + firewallProvider.getName()); } }