blob: 8ada819c7a3e011af8e92c9ead3733ac2a12355d [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network.resource;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.StringReader;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.ConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory;
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;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer;
import com.cloud.agent.api.ExternalNetworkResourceUsageCommand;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalFirewallCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SetFirewallRulesCommand;
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand.UsernamePassword;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StaticNatRuleTO;
import com.cloud.host.Host;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.resource.ServerResource;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.script.Script;
public class JuniperSrxResource implements ServerResource {
private String _name;
private String _zoneId;
private String _ip;
private String _username;
private String _password;
private String _guid;
private String _objectNameWordSep;
private BufferedWriter _toSrx;
private BufferedReader _fromSrx;
private BufferedWriter _UsagetoSrx;
private BufferedReader _UsagefromSrx;
private Integer _numRetries;
private Integer _timeoutInSeconds;
private String _publicZone;
private String _privateZone;
private String _publicZoneInputFilterName;
private String _publicInterface;
private String _usageInterface;
private String _privateInterface;
private String _ikeProposalName;
private String _ipsecPolicyName;
private String _primaryDnsAddress;
private String _ikeGatewayHostname;
private String _vpnObjectPrefix;
private UsageFilter _usageFilterVlanInput;
private UsageFilter _usageFilterVlanOutput;
private UsageFilter _usageFilterIPInput;
private UsageFilter _usageFilterIPOutput;
private static final Logger s_logger = Logger.getLogger(JuniperSrxResource.class);
private enum SrxXml {
LOGIN("login.xml"),
PRIVATE_INTERFACE_ADD("private-interface-add.xml"),
PRIVATE_INTERFACE_WITH_FILTERS_ADD("private-interface-with-filters-add.xml"),
PRIVATE_INTERFACE_GETONE("private-interface-getone.xml"),
PROXY_ARP_ADD("proxy-arp-add.xml"),
PROXY_ARP_GETONE("proxy-arp-getone.xml"),
PROXY_ARP_GETALL("proxy-arp-getall.xml"),
ZONE_INTERFACE_ADD("zone-interface-add.xml"),
ZONE_INTERFACE_GETONE("zone-interface-getone.xml"),
SRC_NAT_POOL_ADD("src-nat-pool-add.xml"),
SRC_NAT_POOL_GETONE("src-nat-pool-getone.xml"),
SRC_NAT_RULE_ADD("src-nat-rule-add.xml"),
SRC_NAT_RULE_GETONE("src-nat-rule-getone.xml"),
SRC_NAT_RULE_GETALL("src-nat-rule-getall.xml"),
DEST_NAT_POOL_ADD("dest-nat-pool-add.xml"),
DEST_NAT_POOL_GETONE("dest-nat-pool-getone.xml"),
DEST_NAT_POOL_GETALL("dest-nat-pool-getall.xml"),
DEST_NAT_RULE_ADD("dest-nat-rule-add.xml"),
DEST_NAT_RULE_GETONE("dest-nat-rule-getone.xml"),
DEST_NAT_RULE_GETALL("dest-nat-rule-getall.xml"),
STATIC_NAT_RULE_ADD("static-nat-rule-add.xml"),
STATIC_NAT_RULE_GETONE("static-nat-rule-getone.xml"),
STATIC_NAT_RULE_GETALL("static-nat-rule-getall.xml"),
ADDRESS_BOOK_ENTRY_ADD("address-book-entry-add.xml"),
ADDRESS_BOOK_ENTRY_GETONE("address-book-entry-getone.xml"),
ADDRESS_BOOK_ENTRY_GETALL("address-book-entry-getall.xml"),
APPLICATION_ADD("application-add.xml"),
APPLICATION_GETONE("application-getone.xml"),
SECURITY_POLICY_ADD("security-policy-add.xml"),
SECURITY_POLICY_GETONE("security-policy-getone.xml"),
SECURITY_POLICY_GETALL("security-policy-getall.xml"),
SECURITY_POLICY_GROUP("security-policy-group.xml"),
GUEST_VLAN_FILTER_TERM_ADD("guest-vlan-filter-term-add.xml"),
PUBLIC_IP_FILTER_TERM_ADD("public-ip-filter-term-add.xml"),
FILTER_TERM_GETONE("filter-term-getone.xml"),
FILTER_GETONE("filter-getone.xml"),
FIREWALL_FILTER_BYTES_GETALL("firewall-filter-bytes-getall.xml"),
IKE_POLICY_ADD("ike-policy-add.xml"),
IKE_POLICY_GETONE("ike-policy-getone.xml"),
IKE_POLICY_GETALL("ike-policy-getall.xml"),
IKE_GATEWAY_ADD("ike-gateway-add.xml"),
IKE_GATEWAY_GETONE("ike-gateway-getone.xml"),
IKE_GATEWAY_GETALL("ike-gateway-getall.xml"),
IPSEC_VPN_ADD("ipsec-vpn-add.xml"),
IPSEC_VPN_GETONE("ipsec-vpn-getone.xml"),
IPSEC_VPN_GETALL("ipsec-vpn-getall.xml"),
DYNAMIC_VPN_CLIENT_ADD("dynamic-vpn-client-add.xml"),
DYNAMIC_VPN_CLIENT_GETONE("dynamic-vpn-client-getone.xml"),
DYNAMIC_VPN_CLIENT_GETALL("dynamic-vpn-client-getall.xml"),
ADDRESS_POOL_ADD("address-pool-add.xml"),
ADDRESS_POOL_GETONE("address-pool-getone.xml"),
ADDRESS_POOL_GETALL("address-pool-getall.xml"),
ACCESS_PROFILE_ADD("access-profile-add.xml"),
ACCESS_PROFILE_GETONE("access-profile-getone.xml"),
ACCESS_PROFILE_GETALL("access-profile-getall.xml"),
FIREWALL_FILTER_TERM_ADD("firewall-filter-term-add.xml"),
FIREWALL_FILTER_TERM_GETONE("firewall-filter-term-getone.xml"),
TEMPLATE_ENTRY("template-entry.xml"),
OPEN_CONFIGURATION("open-configuration.xml"),
CLOSE_CONFIGURATION("close-configuration.xml"),
COMMIT("commit.xml"),
ROLLBACK("rollback.xml"),
TEST("test.xml");
private final String scriptsDir = "scripts/network/juniper";
private final String xml;
private static final Logger s_logger = Logger.getLogger(JuniperSrxResource.class);
private SrxXml(String filename) {
xml = getXml(filename);
}
public String getXml() {
return xml;
}
private String getXml(String filename) {
try {
String xmlFilePath = Script.findScript(scriptsDir, filename);
if (xmlFilePath == null) {
throw new Exception("Failed to find Juniper SRX XML file: " + filename);
}
try(InputStreamReader fr = new InputStreamReader(new FileInputStream(xmlFilePath),"UTF-8");
BufferedReader br = new BufferedReader(fr);) {
String xml = "";
String line;
while ((line = br.readLine()) != null) {
xml += line.trim();
}
return xml;
}catch (Exception e) {
s_logger.debug(e);
return null;
}
} catch (Exception e) {
s_logger.debug(e);
return null;
}
}
}
public class UsageFilter {
private final String name;
private final String counterIdentifier;
private final String addressType;
private UsageFilter(String name, String addressType, String counterIdentifier) {
this.name = name;
this.addressType = addressType;
if (_usageInterface != null) {
counterIdentifier = _usageInterface + counterIdentifier;
}
this.counterIdentifier = counterIdentifier;
}
public String getName() {
return name;
}
public String getCounterIdentifier() {
return counterIdentifier;
}
public String getAddressType() {
return addressType;
}
}
public class FirewallFilterTerm {
private final String name;
private final List<String> sourceCidrs;
private final String destIp;
private String portRange;
private final String protocol;
private String icmpType;
private String icmpCode;
private final String countName;
private FirewallFilterTerm(String name, List<String> sourceCidrs, String destIp, String protocol, Integer startPort, Integer endPort, Integer icmpType,
Integer icmpCode, String countName) {
this.name = name;
this.sourceCidrs = sourceCidrs;
this.destIp = destIp;
this.protocol = protocol;
if (protocol.equals("tcp") || protocol.equals("udp")) {
portRange = String.valueOf(startPort) + "-" + String.valueOf(endPort);
} else if (protocol.equals("icmp")) {
this.icmpType = String.valueOf(icmpType);
this.icmpCode = String.valueOf(icmpCode);
} else {
assert protocol.equals("any");
}
this.countName = countName;
}
public String getName() {
return name;
}
public List<String> getSourceCidrs() {
return sourceCidrs;
}
public String getDestIp() {
return destIp;
}
public String getPortRange() {
return portRange;
}
public String getProtocol() {
return protocol;
}
public String getIcmpType() {
return icmpType;
}
public String getIcmpCode() {
return icmpCode;
}
public String getCountName() {
return countName;
}
}
private enum SrxCommand {
LOGIN, OPEN_CONFIGURATION, CLOSE_CONFIGURATION, COMMIT, ROLLBACK, CHECK_IF_EXISTS, CHECK_IF_IN_USE, ADD, DELETE, GET_ALL, CHECK_PRIVATE_IF_EXISTS;
}
private enum Protocol {
tcp, udp, icmp, all, any;
}
private enum RuleMatchCondition {
ALL, PUBLIC_PRIVATE_IPS, PRIVATE_SUBNET;
}
private enum GuestNetworkType {
SOURCE_NAT, INTERFACE_NAT;
}
private enum SecurityPolicyType {
STATIC_NAT("staticnat"), DESTINATION_NAT("destnat"), VPN("vpn"), SECURITYPOLICY_EGRESS("egress"), SECURITYPOLICY_EGRESS_DEFAULT("egress-default");
private final String identifier;
private SecurityPolicyType(String identifier) {
this.identifier = identifier;
}
private String getIdentifier() {
return identifier;
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand)cmd);
} else if (cmd instanceof MaintainCommand) {
return execute((MaintainCommand)cmd);
} else if (cmd instanceof IpAssocCommand) {
return execute((IpAssocCommand)cmd);
} else if (cmd instanceof SetStaticNatRulesCommand) {
return execute((SetStaticNatRulesCommand)cmd);
} else if (cmd instanceof SetPortForwardingRulesCommand) {
return execute((SetPortForwardingRulesCommand)cmd);
} else if (cmd instanceof SetFirewallRulesCommand) {
return execute((SetFirewallRulesCommand)cmd);
} else if (cmd instanceof ExternalNetworkResourceUsageCommand) {
return execute((ExternalNetworkResourceUsageCommand)cmd);
} else if (cmd instanceof RemoteAccessVpnCfgCommand) {
return execute((RemoteAccessVpnCfgCommand)cmd);
} else if (cmd instanceof VpnUsersCfgCommand) {
return execute((VpnUsersCfgCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
try {
_name = (String)params.get("name");
if (_name == null) {
throw new ConfigurationException("Unable to find name");
}
_zoneId = (String)params.get("zoneId");
if (_zoneId == null) {
throw new ConfigurationException("Unable to find zone");
}
_ip = (String)params.get("ip");
if (_ip == null) {
throw new ConfigurationException("Unable to find IP");
}
_username = (String)params.get("username");
if (_username == null) {
throw new ConfigurationException("Unable to find username");
}
_password = (String)params.get("password");
if (_password == null) {
throw new ConfigurationException("Unable to find password");
}
_publicInterface = (String)params.get("publicinterface");
if (_publicInterface == null) {
throw new ConfigurationException("Unable to find public interface.");
}
_privateInterface = (String)params.get("privateinterface");
if (_privateInterface == null) {
throw new ConfigurationException("Unable to find private interface.");
}
_publicZone = (String)params.get("publiczone");
if (_publicZone == null) {
_publicZone = "untrust";
}
_privateZone = (String)params.get("privatezone");
if (_privateZone == null) {
_privateZone = "trust";
}
_guid = (String)params.get("guid");
if (_guid == null) {
throw new ConfigurationException("Unable to find the guid");
}
_numRetries = NumbersUtil.parseInt((String)params.get("numretries"), 1);
_timeoutInSeconds = NumbersUtil.parseInt((String)params.get("timeout"), 300);
_objectNameWordSep = "-";
_ikeProposalName = "cloud-ike-proposal";
_ipsecPolicyName = "cloud-ipsec-policy";
_ikeGatewayHostname = "cloud";
_vpnObjectPrefix = "vpn-a";
_primaryDnsAddress = "4.2.2.2";
// Open a socket and login
if (!refreshSrxConnection()) {
throw new ConfigurationException("Unable to open a connection to the SRX.");
}
_publicZoneInputFilterName = _publicZone;
_usageFilterVlanInput = new UsageFilter("vlan-input", null, "vlan-input");
_usageFilterVlanOutput = new UsageFilter("vlan-output", null, "vlan-output");
_usageFilterIPInput = new UsageFilter(_publicZone, "destination-address", "-i");
_usageFilterIPOutput = new UsageFilter(_privateZone, "source-address", "-o");
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
}
}
@Override
public StartupCommand[] initialize() {
StartupExternalFirewallCommand cmd = new StartupExternalFirewallCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod("");
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion(JuniperSrxResource.class.getPackage().getImplementationVersion());
cmd.setGuid(_guid);
return new StartupCommand[] {cmd};
}
@Override
public Host.Type getType() {
return Host.Type.ExternalFirewall;
}
@Override
public String getName() {
return _name;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public PingCommand getCurrentStatus(final long id) {
return new PingCommand(Host.Type.ExternalFirewall, id);
}
@Override
public void disconnected() {
closeSocket();
}
@Override
public IAgentControl getAgentControl() {
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
return;
}
private Answer execute(ReadyCommand cmd) {
return new ReadyAnswer(cmd);
}
private Answer execute(MaintainCommand cmd) {
return new MaintainAnswer(cmd);
}
private ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) {
try {
return getUsageAnswer(cmd);
} catch (ExecutionException e) {
return new ExternalNetworkResourceUsageAnswer(cmd, e);
}
}
/*
* Login
*/
private boolean refreshSrxConnection() {
if (!(closeSocket() && openSocket())) {
return false;
}
try {
return login();
} catch (ExecutionException e) {
s_logger.error("Failed to login due to " + e.getMessage());
return false;
}
}
private boolean login() throws ExecutionException {
String xml = SrxXml.LOGIN.getXml();
xml = replaceXmlValue(xml, "username", _username);
xml = replaceXmlValue(xml, "password", _password);
return sendRequestAndCheckResponse(SrxCommand.LOGIN, xml);
}
private boolean openSocket() {
try {
Socket s = new Socket(_ip, 3221);
s.setKeepAlive(true);
s.setSoTimeout(_timeoutInSeconds * 1000);
_toSrx = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
_fromSrx = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
return true;
} catch (IOException e) {
s_logger.error(e);
return false;
}
}
private boolean closeSocket() {
try {
if (_toSrx != null) {
_toSrx.close();
}
if (_fromSrx != null) {
_fromSrx.close();
}
return true;
} catch (IOException e) {
s_logger.error(e);
return false;
}
}
/*
* The usage data will be handled on it's own socket, so usage
* commands will use the following methods...
*/
private boolean usageLogin() throws ExecutionException {
String xml = SrxXml.LOGIN.getXml();
xml = replaceXmlValue(xml, "username", _username);
xml = replaceXmlValue(xml, "password", _password);
return sendUsageRequestAndCheckResponse(SrxCommand.LOGIN, xml);
}
private boolean openUsageSocket() throws ExecutionException {
try {
Socket s = new Socket(_ip, 3221);
s.setKeepAlive(true);
s.setSoTimeout(_timeoutInSeconds * 1000);
_UsagetoSrx = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
_UsagefromSrx = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
return usageLogin();
} catch (IOException e) {
s_logger.error(e);
return false;
}
}
private boolean closeUsageSocket() {
try {
if (_UsagetoSrx != null) {
_UsagetoSrx.close();
}
if (_UsagefromSrx != null) {
_UsagefromSrx.close();
}
return true;
} catch (IOException e) {
s_logger.error(e);
return false;
}
}
/*
* Commit/rollback
*/
private void openConfiguration() throws ExecutionException {
String xml = SrxXml.OPEN_CONFIGURATION.getXml();
String successMsg = "Opened a private configuration.";
String errorMsg = "Failed to open a private configuration.";
if (!sendRequestAndCheckResponse(SrxCommand.OPEN_CONFIGURATION, xml)) {
throw new ExecutionException(errorMsg);
} else {
s_logger.debug(successMsg);
}
}
private void closeConfiguration() {
String xml = SrxXml.CLOSE_CONFIGURATION.getXml();
String successMsg = "Closed private configuration.";
String errorMsg = "Failed to close private configuration.";
try {
if (!sendRequestAndCheckResponse(SrxCommand.CLOSE_CONFIGURATION, xml)) {
s_logger.error(errorMsg);
}
} catch (ExecutionException e) {
s_logger.error(errorMsg);
}
s_logger.debug(successMsg);
}
private void commitConfiguration() throws ExecutionException {
String xml = SrxXml.COMMIT.getXml();
String successMsg = "Committed to global configuration.";
String errorMsg = "Failed to commit to global configuration.";
if (!sendRequestAndCheckResponse(SrxCommand.COMMIT, xml)) {
throw new ExecutionException(errorMsg);
} else {
s_logger.debug(successMsg);
closeConfiguration();
}
}
/*
* Guest networks
*/
private synchronized Answer execute(IpAssocCommand cmd) {
refreshSrxConnection();
return execute(cmd, _numRetries);
}
private Answer execute(IpAssocCommand cmd, int numRetries) {
String[] results = new String[cmd.getIpAddresses().length];
int i = 0;
try {
IpAddressTO ip;
if (cmd.getIpAddresses().length != 1) {
throw new ExecutionException("Received an invalid number of guest IPs to associate.");
} else {
ip = cmd.getIpAddresses()[0];
}
String sourceNatIpAddress = null;
GuestNetworkType type = GuestNetworkType.INTERFACE_NAT;
if (ip.isSourceNat()) {
type = GuestNetworkType.SOURCE_NAT;
if (ip.getPublicIp() == null) {
throw new ExecutionException("Source NAT IP address must not be null.");
} else {
sourceNatIpAddress = ip.getPublicIp();
}
}
long guestVlanTag = Long.parseLong(cmd.getAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG));
String guestVlanGateway = cmd.getAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY);
String cidr = cmd.getAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR);
long cidrSize = NetUtils.cidrToLong(cidr)[1];
String guestVlanSubnet = NetUtils.getCidrSubNet(guestVlanGateway, cidrSize);
Long publicVlanTag = null;
if (ip.getBroadcastUri() != null && !ip.getBroadcastUri().equals("untagged")) {
try {
publicVlanTag = Long.parseLong(BroadcastDomainType.getValue(ip.getBroadcastUri()));
} catch (Exception e) {
throw new ExecutionException("Could not parse public VLAN tag: " + ip.getBroadcastUri());
}
}
openConfiguration();
// Remove the guest network:
// Remove source, static, and destination NAT rules
// Remove VPN
shutdownGuestNetwork(type, ip.getAccountId(), publicVlanTag, sourceNatIpAddress, guestVlanTag, guestVlanGateway, guestVlanSubnet, cidrSize);
if (ip.isAdd()) {
// Implement the guest network for this VLAN
implementGuestNetwork(type, publicVlanTag, sourceNatIpAddress, guestVlanTag, guestVlanGateway, guestVlanSubnet, cidrSize);
}
commitConfiguration();
results[i++] = ip.getPublicIp() + " - success";
} catch (ExecutionException e) {
s_logger.error(e);
closeConfiguration();
if (numRetries > 0 && refreshSrxConnection()) {
int numRetriesRemaining = numRetries - 1;
s_logger.debug("Retrying IPAssocCommand. Number of retries remaining: " + numRetriesRemaining);
return execute(cmd, numRetriesRemaining);
} else {
results[i++] = IpAssocAnswer.errorResult;
}
}
return new IpAssocAnswer(cmd, results);
}
private void implementGuestNetwork(GuestNetworkType type, Long publicVlanTag, String publicIp, long privateVlanTag, String privateGateway, String privateSubnet,
long privateCidrNumber) throws ExecutionException {
privateGateway = privateGateway + "/" + privateCidrNumber;
privateSubnet = privateSubnet + "/" + privateCidrNumber;
managePrivateInterface(SrxCommand.ADD, !type.equals(GuestNetworkType.SOURCE_NAT), privateVlanTag, privateGateway);
manageZoneInterface(SrxCommand.ADD, privateVlanTag);
if (type.equals(GuestNetworkType.SOURCE_NAT)) {
manageSourceNatPool(SrxCommand.ADD, publicIp);
manageSourceNatRule(SrxCommand.ADD, publicIp, privateSubnet);
manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp);
manageUsageFilter(SrxCommand.ADD, _usageFilterIPOutput, privateSubnet, null, genIpFilterTermName(publicIp));
manageUsageFilter(SrxCommand.ADD, _usageFilterIPInput, publicIp, null, genIpFilterTermName(publicIp));
} else if (type.equals(GuestNetworkType.INTERFACE_NAT)) {
manageUsageFilter(SrxCommand.ADD, _usageFilterVlanOutput, null, privateVlanTag, null);
manageUsageFilter(SrxCommand.ADD, _usageFilterVlanInput, null, privateVlanTag, null);
}
String msg = "Implemented guest network with type " + type + ". Guest VLAN tag: " + privateVlanTag + ", guest gateway: " + privateGateway;
msg += type.equals(GuestNetworkType.SOURCE_NAT) ? ", source NAT IP: " + publicIp : "";
s_logger.debug(msg);
}
private void shutdownGuestNetwork(GuestNetworkType type, long accountId, Long publicVlanTag, String sourceNatIpAddress, long privateVlanTag, String privateGateway,
String privateSubnet, long privateCidrSize) throws ExecutionException {
// Remove static and destination NAT rules for the guest network
removeStaticAndDestNatRulesInPrivateVlan(privateVlanTag, privateGateway, privateCidrSize);
privateGateway = privateGateway + "/" + privateCidrSize;
privateSubnet = privateSubnet + "/" + privateCidrSize;
managePrivateInterface(SrxCommand.DELETE, false, privateVlanTag, privateGateway);
manageZoneInterface(SrxCommand.DELETE, privateVlanTag);
deleteVpnObjectsForAccount(accountId);
if (type.equals(GuestNetworkType.SOURCE_NAT)) {
manageSourceNatRule(SrxCommand.DELETE, sourceNatIpAddress, privateSubnet);
manageSourceNatPool(SrxCommand.DELETE, sourceNatIpAddress);
manageProxyArp(SrxCommand.DELETE, publicVlanTag, sourceNatIpAddress);
manageUsageFilter(SrxCommand.DELETE, _usageFilterIPOutput, privateSubnet, null, genIpFilterTermName(sourceNatIpAddress));
manageUsageFilter(SrxCommand.DELETE, _usageFilterIPInput, sourceNatIpAddress, null, genIpFilterTermName(sourceNatIpAddress));
} else if (type.equals(GuestNetworkType.INTERFACE_NAT)) {
manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanOutput, null, privateVlanTag, null);
manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanInput, null, privateVlanTag, null);
}
String msg = "Shut down guest network with type " + type + ". Guest VLAN tag: " + privateVlanTag + ", guest gateway: " + privateGateway;
msg += type.equals(GuestNetworkType.SOURCE_NAT) ? ", source NAT IP: " + sourceNatIpAddress : "";
s_logger.debug(msg);
}
private Map<String, ArrayList<FirewallRuleTO>> getActiveFirewallEgressRules(FirewallRuleTO[] allRules) {
Map<String, ArrayList<FirewallRuleTO>> activeRules = new HashMap<String, ArrayList<FirewallRuleTO>>();
for (FirewallRuleTO rule : allRules) {
String guestVlan;
guestVlan = rule.getSrcVlanTag();
ArrayList<FirewallRuleTO> activeRulesForNetwork = activeRules.get(guestVlan);
if (activeRulesForNetwork == null) {
activeRulesForNetwork = new ArrayList<FirewallRuleTO>();
}
if (!rule.revoked() || rule.isAlreadyAdded()) {
activeRulesForNetwork.add(rule);
}
activeRules.put(guestVlan, activeRulesForNetwork);
}
return activeRules;
}
private List<String> extractCidrs(List<FirewallRuleTO> rules) throws ExecutionException {
List<String> allCidrs = new ArrayList<String>();
List<String> cidrs = new ArrayList<String>();
for (FirewallRuleTO rule : rules) {
cidrs = (rule.getSourceCidrList());
for (String cidr : cidrs) {
if (!allCidrs.contains(cidr)) {
allCidrs.add(cidr);
}
}
}
return allCidrs;
}
/* security policies */
private synchronized Answer execute(SetFirewallRulesCommand cmd) {
refreshSrxConnection();
return execute(cmd, _numRetries);
}
private Answer execute(SetFirewallRulesCommand cmd, int numRetries) {
FirewallRuleTO[] rules = cmd.getRules();
try {
openConfiguration();
if (rules[0].getTrafficType() == FirewallRule.TrafficType.Egress) {
Map<String, ArrayList<FirewallRuleTO>> activeRules = getActiveFirewallEgressRules(rules);
Set<String> guestVlans = activeRules.keySet();
// List<String> cidrs = new ArrayList();
boolean defaultEgressPolicy = rules[0].isDefaultEgressPolicy();
FirewallRule.FirewallRuleType type = rules[0].getType();
//getting
String guestCidr = rules[0].getGuestCidr();
List<String> cidrs = new ArrayList<String>();
cidrs.add(guestCidr);
List<Object[]> applications = new ArrayList<Object[]>();
Object[] application = new Object[3];
application[0] = Protocol.all;
application[1] = NetUtils.PORT_RANGE_MIN;
application[2] = NetUtils.PORT_RANGE_MAX;
applications.add(application);
for (String guestVlan : guestVlans) {
List<FirewallRuleTO> activeRulesForGuestNw = activeRules.get(guestVlan);
removeEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS, guestVlan, extractCidrs(activeRulesForGuestNw),
defaultEgressPolicy);
if (activeRulesForGuestNw.size() > 0 && type == FirewallRule.FirewallRuleType.User) {
addEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS, guestVlan, extractApplications(activeRulesForGuestNw),
extractCidrs(activeRulesForGuestNw), defaultEgressPolicy);
/* Adding default policy rules are required because the order of rules is important.
* Depending on the rules order the traffic accept/drop is performed
*/
removeEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT, guestVlan, cidrs, defaultEgressPolicy);
addEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT, guestVlan, applications, cidrs, defaultEgressPolicy);
}
//remove required with out comparing default policy because in upgrade network offering we may required to delete
// the previously added rule
removeEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT, guestVlan, cidrs, false);
if (defaultEgressPolicy == true && type == FirewallRule.FirewallRuleType.System) {
removeEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT, guestVlan, cidrs, defaultEgressPolicy);
if (activeRulesForGuestNw.size() > 0) {
//add default egress security policy
addEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT, guestVlan, applications, cidrs, defaultEgressPolicy);
}
}
}
commitConfiguration();
} else {
for (FirewallRuleTO rule : rules) {
int startPort = NetUtils.PORT_RANGE_MIN, endPort = NetUtils.PORT_RANGE_MAX;
if (rule.getSrcPortRange() != null) {
startPort = rule.getSrcPortRange()[0];
endPort = rule.getSrcPortRange()[1];
}
FirewallFilterTerm term =
new FirewallFilterTerm(genIpIdentifier(rule.getSrcIp()) + "-" + String.valueOf(rule.getId()), rule.getSourceCidrList(), rule.getSrcIp(),
rule.getProtocol(), startPort, endPort, rule.getIcmpType(), rule.getIcmpCode(), genIpIdentifier(rule.getSrcIp()) +
_usageFilterIPInput.getCounterIdentifier());
if (!rule.revoked()) {
manageProxyArp(SrxCommand.ADD, getVlanTag(rule.getSrcVlanTag()), rule.getSrcIp());
manageFirewallFilter(SrxCommand.ADD, term, _publicZoneInputFilterName);
} else {
manageFirewallFilter(SrxCommand.DELETE, term, _publicZoneInputFilterName);
manageProxyArp(SrxCommand.DELETE, getVlanTag(rule.getSrcVlanTag()), rule.getSrcIp());
}
}
commitConfiguration();
}
return new Answer(cmd);
} catch (ExecutionException e) {
s_logger.error(e);
closeConfiguration();
if (numRetries > 0 && refreshSrxConnection()) {
int numRetriesRemaining = numRetries - 1;
s_logger.debug("Retrying SetFirewallRulesCommand. Number of retries remaining: " + numRetriesRemaining);
return execute(cmd, numRetriesRemaining);
} else {
return new Answer(cmd, e);
}
}
}
/*
* Static NAT
*/
private synchronized Answer execute(SetStaticNatRulesCommand cmd) {
refreshSrxConnection();
return execute(cmd, _numRetries);
}
private Answer execute(SetStaticNatRulesCommand cmd, int numRetries) {
StaticNatRuleTO[] allRules = cmd.getRules();
Map<String, ArrayList<FirewallRuleTO>> activeRules = getActiveRules(allRules);
Map<String, String> vlanTagMap = getVlanTagMap(allRules);
try {
openConfiguration();
Set<String> ipPairs = activeRules.keySet();
for (String ipPair : ipPairs) {
String[] ipPairComponents = ipPair.split("-");
String publicIp = ipPairComponents[0];
String privateIp = ipPairComponents[1];
List<FirewallRuleTO> activeRulesForIpPair = activeRules.get(ipPair);
Long publicVlanTag = getVlanTag(vlanTagMap.get(publicIp));
// Delete the existing static NAT rule for this IP pair
removeStaticNatRule(publicVlanTag, publicIp, privateIp);
if (activeRulesForIpPair.size() > 0) {
// If there are active FirewallRules for this IP pair, add the static NAT rule and open the specified port ranges
addStaticNatRule(publicVlanTag, publicIp, privateIp, activeRulesForIpPair);
}
}
commitConfiguration();
return new Answer(cmd);
} catch (ExecutionException e) {
s_logger.error(e);
closeConfiguration();
if (numRetries > 0 && refreshSrxConnection()) {
int numRetriesRemaining = numRetries - 1;
s_logger.debug("Retrying SetPortForwardingRulesCommand. Number of retries remaining: " + numRetriesRemaining);
return execute(cmd, numRetriesRemaining);
} else {
return new Answer(cmd, e);
}
}
}
private void addStaticNatRule(Long publicVlanTag, String publicIp, String privateIp, List<FirewallRuleTO> rules) throws ExecutionException {
manageStaticNatRule(SrxCommand.ADD, publicIp, privateIp);
manageAddressBookEntry(SrxCommand.ADD, _privateZone, privateIp, null);
manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp);
// Add a new security policy with the current set of applications
addSecurityPolicyAndApplications(SecurityPolicyType.STATIC_NAT, privateIp, extractApplications(rules));
s_logger.debug("Added static NAT rule for public IP " + publicIp + ", and private IP " + privateIp);
}
private void removeStaticNatRule(Long publicVlanTag, String publicIp, String privateIp) throws ExecutionException {
manageStaticNatRule(SrxCommand.DELETE, publicIp, privateIp);
// Remove any existing security policy and clean up applications
removeSecurityPolicyAndApplications(SecurityPolicyType.STATIC_NAT, privateIp);
manageAddressBookEntry(SrxCommand.DELETE, _privateZone, privateIp, null);
manageProxyArp(SrxCommand.DELETE, publicVlanTag, publicIp);
s_logger.debug("Removed static NAT rule for public IP " + publicIp + ", and private IP " + privateIp);
}
private void removeStaticNatRules(Long privateVlanTag, Map<String, Long> publicVlanTags, List<String[]> staticNatRules) throws ExecutionException {
for (String[] staticNatRuleToRemove : staticNatRules) {
String staticNatRulePublicIp = staticNatRuleToRemove[0];
String staticNatRulePrivateIp = staticNatRuleToRemove[1];
Long publicVlanTag = null;
if (publicVlanTags.containsKey(staticNatRulePublicIp)) {
publicVlanTag = publicVlanTags.get(staticNatRulePublicIp);
}
if (privateVlanTag != null) {
s_logger.warn("Found a static NAT rule (" + staticNatRulePublicIp + " <-> " + staticNatRulePrivateIp + ") for guest VLAN with tag " + privateVlanTag +
" that is active when the guest network is being removed. Removing rule...");
}
removeStaticNatRule(publicVlanTag, staticNatRulePublicIp, staticNatRulePrivateIp);
}
}
/*
* VPN
*/
private synchronized Answer execute(RemoteAccessVpnCfgCommand cmd) {
refreshSrxConnection();
return execute(cmd, _numRetries);
}
private Answer execute(RemoteAccessVpnCfgCommand cmd, int numRetries) {
long accountId = Long.parseLong(cmd.getAccessDetail(NetworkElementCommand.ACCOUNT_ID));
String guestNetworkCidr = cmd.getAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR);
String preSharedKey = cmd.getPresharedKey();
String[] ipRange = cmd.getIpRange().split("-");
try {
openConfiguration();
// Delete existing VPN objects for this account
deleteVpnObjectsForAccount(accountId);
if (cmd.isCreate()) {
// Add IKE policy
manageIkePolicy(SrxCommand.ADD, null, accountId, preSharedKey);
// Add address pool
manageAddressPool(SrxCommand.ADD, null, accountId, guestNetworkCidr, ipRange[0], ipRange[1], _primaryDnsAddress);
}
commitConfiguration();
return new Answer(cmd);
} catch (ExecutionException e) {
s_logger.error(e);
closeConfiguration();
if (numRetries > 0 && refreshSrxConnection()) {
int numRetriesRemaining = numRetries - 1;
s_logger.debug("Retrying RemoteAccessVpnCfgCommand. Number of retries remaining: " + numRetriesRemaining);
return execute(cmd, numRetriesRemaining);
} else {
return new Answer(cmd, e);
}
}
}
private void deleteVpnObjectsForAccount(long accountId) throws ExecutionException {
// Delete all IKE policies
for (String ikePolicyName : getVpnObjectNames(SrxXml.IKE_POLICY_GETALL, accountId)) {
manageIkePolicy(SrxCommand.DELETE, ikePolicyName, null, null);
}
// Delete all address pools
for (String addressPoolName : getVpnObjectNames(SrxXml.ADDRESS_POOL_GETALL, accountId)) {
manageAddressPool(SrxCommand.DELETE, addressPoolName, null, null, null, null, null);
}
// Delete all IKE gateways
for (String ikeGatewayName : getVpnObjectNames(SrxXml.IKE_GATEWAY_GETALL, accountId)) {
manageIkeGateway(SrxCommand.DELETE, ikeGatewayName, null, null, null, null);
}
// Delete all IPsec VPNs
for (String ipsecVpnName : getVpnObjectNames(SrxXml.IPSEC_VPN_GETALL, accountId)) {
manageIpsecVpn(SrxCommand.DELETE, ipsecVpnName, null, null, null, null);
}
// Delete all dynamic VPN clients
for (String dynamicVpnClientName : getVpnObjectNames(SrxXml.DYNAMIC_VPN_CLIENT_GETALL, accountId)) {
manageDynamicVpnClient(SrxCommand.DELETE, dynamicVpnClientName, null, null, null, null);
}
// Delete all access profiles
for (String accessProfileName : getVpnObjectNames(SrxXml.ACCESS_PROFILE_GETALL, accountId)) {
manageAccessProfile(SrxCommand.DELETE, accessProfileName, null, null, null, null);
}
// Delete all security policies
for (String securityPolicyName : getVpnObjectNames(SrxXml.SECURITY_POLICY_GETALL, accountId)) {
manageSecurityPolicy(SecurityPolicyType.VPN, SrxCommand.DELETE, accountId, null, null, null, null, securityPolicyName, false);
}
// Delete all address book entries
for (String addressBookEntryName : getVpnObjectNames(SrxXml.ADDRESS_BOOK_ENTRY_GETALL, accountId)) {
manageAddressBookEntry(SrxCommand.DELETE, _privateZone, null, addressBookEntryName);
}
}
public List<String> getVpnObjectNames(SrxXml xmlObj, long accountId) throws ExecutionException {
List<String> vpnObjectNames = new ArrayList<String>();
String xmlRequest = xmlObj.getXml();
if (xmlObj.equals(SrxXml.SECURITY_POLICY_GETALL)) {
xmlRequest = replaceXmlValue(xmlRequest, "from-zone", _publicZone);
xmlRequest = replaceXmlValue(xmlRequest, "to-zone", _privateZone);
} else if (xmlObj.equals(SrxXml.ADDRESS_BOOK_ENTRY_GETALL)) {
xmlRequest = replaceXmlValue(xmlRequest, "zone", _privateZone);
}
String xmlResponse = sendRequest(xmlRequest);
Document doc = getDocument(xmlResponse);
NodeList vpnObjectNameNodes = doc.getElementsByTagName("name");
for (int i = 0; i < vpnObjectNameNodes.getLength(); i++) {
NodeList vpnObjectNameEntries = vpnObjectNameNodes.item(i).getChildNodes();
for (int j = 0; j < vpnObjectNameEntries.getLength(); j++) {
String vpnObjectName = vpnObjectNameEntries.item(j).getNodeValue();
if (vpnObjectName.startsWith(genObjectName(_vpnObjectPrefix, String.valueOf(accountId)))) {
vpnObjectNames.add(vpnObjectName);
}
}
}
return vpnObjectNames;
}
private synchronized Answer execute(VpnUsersCfgCommand cmd) {
refreshSrxConnection();
return execute(cmd, _numRetries);
}
private Answer execute(VpnUsersCfgCommand cmd, int numRetries) {
long accountId = Long.parseLong(cmd.getAccessDetail(NetworkElementCommand.ACCOUNT_ID));
String guestNetworkCidr = cmd.getAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR);
String ikePolicyName = genIkePolicyName(accountId);
UsernamePassword[] users = cmd.getUserpwds();
try {
openConfiguration();
for (UsernamePassword user : users) {
SrxCommand srxCmd = user.isAdd() ? SrxCommand.ADD : SrxCommand.DELETE;
String ipsecVpnName = genIpsecVpnName(accountId, user.getUsername());
// IKE gateway
manageIkeGateway(srxCmd, null, accountId, ikePolicyName, _ikeGatewayHostname, user.getUsername());
// IPSec VPN
manageIpsecVpn(srxCmd, null, accountId, guestNetworkCidr, user.getUsername(), _ipsecPolicyName);
// Dynamic VPN client
manageDynamicVpnClient(srxCmd, null, accountId, guestNetworkCidr, ipsecVpnName, user.getUsername());
// Access profile
manageAccessProfile(srxCmd, null, accountId, user.getUsername(), user.getPassword(), genAddressPoolName(accountId));
// Address book entry
manageAddressBookEntry(srxCmd, _privateZone, guestNetworkCidr, ipsecVpnName);
// Security policy
manageSecurityPolicy(SecurityPolicyType.VPN, srxCmd, null, null, guestNetworkCidr, null, null, ipsecVpnName, false);
}
commitConfiguration();
return new Answer(cmd);
} catch (ExecutionException e) {
s_logger.error(e);
closeConfiguration();
if (numRetries > 0 && refreshSrxConnection()) {
int numRetriesRemaining = numRetries - 1;
s_logger.debug("Retrying RemoteAccessVpnCfgCommand. Number of retries remaining: " + numRetriesRemaining);
return execute(cmd, numRetriesRemaining);
} else {
return new Answer(cmd, e);
}
}
}
/*
* Destination NAT
*/
private synchronized Answer execute(SetPortForwardingRulesCommand cmd) {
refreshSrxConnection();
return execute(cmd, _numRetries);
}
private Answer execute(SetPortForwardingRulesCommand cmd, int numRetries) {
PortForwardingRuleTO[] allRules = cmd.getRules();
Map<String, ArrayList<FirewallRuleTO>> activeRules = getActiveRules(allRules);
try {
openConfiguration();
Set<String> ipPairs = activeRules.keySet();
for (String ipPair : ipPairs) {
String[] ipPairComponents = ipPair.split("-");
String publicIp = ipPairComponents[0];
String privateIp = ipPairComponents[1];
List<FirewallRuleTO> activeRulesForIpPair = activeRules.get(ipPair);
// Get a list of all destination NAT rules for the public/private IP address pair
List<String[]> destNatRules = getDestNatRules(RuleMatchCondition.PUBLIC_PRIVATE_IPS, publicIp, privateIp, null, null);
Map<String, Long> publicVlanTags = getPublicVlanTagsForNatRules(destNatRules);
// Delete all of these rules, along with the destination NAT pools and security policies they use
removeDestinationNatRules(null, publicVlanTags, destNatRules);
// If there are active rules for the public/private IP address pair, add them back
for (FirewallRuleTO rule : activeRulesForIpPair) {
Long publicVlanTag = getVlanTag(rule.getSrcVlanTag());
PortForwardingRuleTO portForwardingRule = (PortForwardingRuleTO)rule;
addDestinationNatRule(getProtocol(rule.getProtocol()), publicVlanTag, portForwardingRule.getSrcIp(), portForwardingRule.getDstIp(),
portForwardingRule.getSrcPortRange()[0], portForwardingRule.getSrcPortRange()[1], portForwardingRule.getDstPortRange()[0],
portForwardingRule.getDstPortRange()[1]);
}
}
commitConfiguration();
return new Answer(cmd);
} catch (ExecutionException e) {
s_logger.error(e);
closeConfiguration();
if (numRetries > 0 && refreshSrxConnection()) {
int numRetriesRemaining = numRetries - 1;
s_logger.debug("Retrying SetPortForwardingRulesCommand. Number of retries remaining: " + numRetriesRemaining);
return execute(cmd, numRetriesRemaining);
} else {
return new Answer(cmd, e);
}
}
}
private void addDestinationNatRule(Protocol protocol, Long publicVlanTag, String publicIp, String privateIp, int srcPortStart, int srcPortEnd, int destPortStart,
int destPortEnd) throws ExecutionException {
int offset = 0;
for (int srcPort = srcPortStart; srcPort <= srcPortEnd; srcPort++) {
int destPort = destPortStart + offset;
manageDestinationNatPool(SrxCommand.ADD, privateIp, destPort);
manageDestinationNatRule(SrxCommand.ADD, publicIp, privateIp, srcPort, destPort);
offset += 1;
}
manageAddressBookEntry(SrxCommand.ADD, _privateZone, privateIp, null);
List<Object[]> applications = new ArrayList<Object[]>();
applications.add(new Object[] {protocol, destPortStart, destPortEnd});
addSecurityPolicyAndApplications(SecurityPolicyType.DESTINATION_NAT, privateIp, applications);
manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp);
String srcPortRange = srcPortStart + "-" + srcPortEnd;
String destPortRange = destPortStart + "-" + destPortEnd;
s_logger.debug("Added destination NAT rule for protocol " + protocol + ", public IP " + publicIp + ", private IP " + privateIp + ", source port range " +
srcPortRange + ", and dest port range " + destPortRange);
}
private void removeDestinationNatRule(Long publicVlanTag, String publicIp, String privateIp, int srcPort, int destPort) throws ExecutionException {
manageDestinationNatRule(SrxCommand.DELETE, publicIp, privateIp, srcPort, destPort);
manageDestinationNatPool(SrxCommand.DELETE, privateIp, destPort);
manageProxyArp(SrxCommand.DELETE, publicVlanTag, publicIp);
removeSecurityPolicyAndApplications(SecurityPolicyType.DESTINATION_NAT, privateIp);
manageAddressBookEntry(SrxCommand.DELETE, _privateZone, privateIp, null);
s_logger.debug("Removed destination NAT rule for public IP " + publicIp + ", private IP " + privateIp + ", source port " + srcPort + ", and dest port " +
destPort);
}
private void removeDestinationNatRules(Long privateVlanTag, Map<String, Long> publicVlanTags, List<String[]> destNatRules) throws ExecutionException {
for (String[] destNatRule : destNatRules) {
String publicIp = destNatRule[0];
String privateIp = destNatRule[1];
int srcPort = Integer.parseInt(destNatRule[2]);
int destPort = Integer.parseInt(destNatRule[3]);
Long publicVlanTag = null;
if (publicVlanTags.containsKey(publicIp)) {
publicVlanTag = publicVlanTags.get(publicIp);
}
if (privateVlanTag != null) {
s_logger.warn("Found a destination NAT rule (public IP: " + publicIp + ", private IP: " + privateIp + ", public port: " + srcPort + ", private port: " +
destPort + ") for guest VLAN with tag " + privateVlanTag + " that is active when the guest network is being removed. Removing rule...");
}
removeDestinationNatRule(publicVlanTag, publicIp, privateIp, srcPort, destPort);
}
}
/*
* General NAT utils
*/
private List<String[]> getAllStaticAndDestNatRules() throws ExecutionException {
List<String[]> staticAndDestNatRules = new ArrayList<String[]>();
staticAndDestNatRules.addAll(getStaticNatRules(RuleMatchCondition.ALL, null, null));
staticAndDestNatRules.addAll(getDestNatRules(RuleMatchCondition.ALL, null, null, null, null));
return staticAndDestNatRules;
}
private void removeStaticAndDestNatRulesInPrivateVlan(long privateVlanTag, String privateGateway, long privateCidrSize) throws ExecutionException {
List<String[]> staticNatRulesToRemove = getStaticNatRules(RuleMatchCondition.PRIVATE_SUBNET, privateGateway, privateCidrSize);
List<String[]> destNatRulesToRemove = getDestNatRules(RuleMatchCondition.PRIVATE_SUBNET, null, null, privateGateway, privateCidrSize);
List<String> publicIps = new ArrayList<String>();
addPublicIpsToList(staticNatRulesToRemove, publicIps);
addPublicIpsToList(destNatRulesToRemove, publicIps);
Map<String, Long> publicVlanTags = getPublicVlanTagsForPublicIps(publicIps);
removeStaticNatRules(privateVlanTag, publicVlanTags, staticNatRulesToRemove);
removeDestinationNatRules(privateVlanTag, publicVlanTags, destNatRulesToRemove);
}
private Map<String, ArrayList<FirewallRuleTO>> getActiveRules(FirewallRuleTO[] allRules) {
Map<String, ArrayList<FirewallRuleTO>> activeRules = new HashMap<String, ArrayList<FirewallRuleTO>>();
for (FirewallRuleTO rule : allRules) {
String ipPair;
if (rule.getPurpose().equals(Purpose.StaticNat)) {
StaticNatRuleTO staticNatRule = (StaticNatRuleTO)rule;
ipPair = staticNatRule.getSrcIp() + "-" + staticNatRule.getDstIp();
} else if (rule.getPurpose().equals(Purpose.PortForwarding)) {
PortForwardingRuleTO portForwardingRule = (PortForwardingRuleTO)rule;
ipPair = portForwardingRule.getSrcIp() + "-" + portForwardingRule.getDstIp();
} else {
continue;
}
ArrayList<FirewallRuleTO> activeRulesForIpPair = activeRules.get(ipPair);
if (activeRulesForIpPair == null) {
activeRulesForIpPair = new ArrayList<FirewallRuleTO>();
}
if (!rule.revoked() || rule.isAlreadyAdded()) {
activeRulesForIpPair.add(rule);
}
activeRules.put(ipPair, activeRulesForIpPair);
}
return activeRules;
}
private Map<String, String> getVlanTagMap(FirewallRuleTO[] allRules) {
Map<String, String> vlanTagMap = new HashMap<String, String>();
for (FirewallRuleTO rule : allRules) {
vlanTagMap.put(rule.getSrcIp(), rule.getSrcVlanTag());
}
return vlanTagMap;
}
/*
* VPN
*/
private String genIkePolicyName(long accountId) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId));
}
private boolean manageIkePolicy(SrxCommand command, String ikePolicyName, Long accountId, String preSharedKey) throws ExecutionException {
if (ikePolicyName == null) {
ikePolicyName = genIkePolicyName(accountId);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.IKE_GATEWAY_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "policy-name", ikePolicyName);
return sendRequestAndCheckResponse(command, xml, "name", ikePolicyName);
case ADD:
if (manageIkePolicy(SrxCommand.CHECK_IF_EXISTS, ikePolicyName, accountId, preSharedKey)) {
return true;
}
xml = SrxXml.IKE_POLICY_ADD.getXml();
xml = replaceXmlValue(xml, "policy-name", ikePolicyName);
xml = replaceXmlValue(xml, "proposal-name", _ikeProposalName);
xml = replaceXmlValue(xml, "pre-shared-key", preSharedKey);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add IKE policy: " + ikePolicyName);
} else {
return true;
}
case DELETE:
if (!manageIkePolicy(SrxCommand.CHECK_IF_EXISTS, ikePolicyName, accountId, preSharedKey)) {
return true;
}
xml = SrxXml.IKE_GATEWAY_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "policy-name", ikePolicyName);
if (!sendRequestAndCheckResponse(command, xml, "name", ikePolicyName)) {
throw new ExecutionException("Failed to delete IKE policy: " + ikePolicyName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private String genIkeGatewayName(long accountId, String username) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId), username);
}
private boolean manageIkeGateway(SrxCommand command, String ikeGatewayName, Long accountId, String ikePolicyName, String ikeGatewayHostname, String username)
throws ExecutionException {
if (ikeGatewayName == null) {
ikeGatewayName = genIkeGatewayName(accountId, username);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.IKE_GATEWAY_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "gateway-name", ikeGatewayName);
return sendRequestAndCheckResponse(command, xml, "name", ikeGatewayName);
case ADD:
if (manageIkeGateway(SrxCommand.CHECK_IF_EXISTS, ikeGatewayName, accountId, ikePolicyName, ikeGatewayHostname, username)) {
return true;
}
xml = SrxXml.IKE_GATEWAY_ADD.getXml();
xml = replaceXmlValue(xml, "gateway-name", ikeGatewayName);
xml = replaceXmlValue(xml, "ike-policy-name", ikePolicyName);
xml = replaceXmlValue(xml, "ike-gateway-hostname", ikeGatewayHostname);
xml = replaceXmlValue(xml, "public-interface-name", _publicInterface);
xml = replaceXmlValue(xml, "access-profile-name", genAccessProfileName(accountId, username));
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add IKE gateway: " + ikeGatewayName);
} else {
return true;
}
case DELETE:
if (!manageIkeGateway(SrxCommand.CHECK_IF_EXISTS, ikeGatewayName, accountId, ikePolicyName, ikeGatewayHostname, username)) {
return true;
}
xml = SrxXml.IKE_GATEWAY_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "gateway-name", ikeGatewayName);
if (!sendRequestAndCheckResponse(command, xml, "name", ikeGatewayName)) {
throw new ExecutionException("Failed to delete IKE gateway: " + ikeGatewayName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private String genIpsecVpnName(long accountId, String username) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId), username);
}
private boolean manageIpsecVpn(SrxCommand command, String ipsecVpnName, Long accountId, String guestNetworkCidr, String username, String ipsecPolicyName)
throws ExecutionException {
if (ipsecVpnName == null) {
ipsecVpnName = genIpsecVpnName(accountId, username);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.IPSEC_VPN_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "ipsec-vpn-name", ipsecVpnName);
return sendRequestAndCheckResponse(command, xml, "name", ipsecVpnName);
case ADD:
if (manageIpsecVpn(SrxCommand.CHECK_IF_EXISTS, ipsecVpnName, accountId, guestNetworkCidr, username, ipsecPolicyName)) {
return true;
}
xml = SrxXml.IPSEC_VPN_ADD.getXml();
xml = replaceXmlValue(xml, "ipsec-vpn-name", ipsecVpnName);
xml = replaceXmlValue(xml, "ike-gateway", genIkeGatewayName(accountId, username));
xml = replaceXmlValue(xml, "ipsec-policy-name", ipsecPolicyName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add IPSec VPN: " + ipsecVpnName);
} else {
return true;
}
case DELETE:
if (!manageIpsecVpn(SrxCommand.CHECK_IF_EXISTS, ipsecVpnName, accountId, guestNetworkCidr, username, ipsecPolicyName)) {
return true;
}
xml = SrxXml.IPSEC_VPN_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "ipsec-vpn-name", ipsecVpnName);
if (!sendRequestAndCheckResponse(command, xml, "name", ipsecVpnName)) {
throw new ExecutionException("Failed to delete IPSec VPN: " + ipsecVpnName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private String genDynamicVpnClientName(long accountId, String username) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId), username);
}
private boolean manageDynamicVpnClient(SrxCommand command, String clientName, Long accountId, String guestNetworkCidr, String ipsecVpnName, String username)
throws ExecutionException {
if (clientName == null) {
clientName = genDynamicVpnClientName(accountId, username);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.DYNAMIC_VPN_CLIENT_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "client-name", clientName);
return sendRequestAndCheckResponse(command, xml, "name", clientName);
case ADD:
if (manageDynamicVpnClient(SrxCommand.CHECK_IF_EXISTS, clientName, accountId, guestNetworkCidr, ipsecVpnName, username)) {
return true;
}
xml = SrxXml.DYNAMIC_VPN_CLIENT_ADD.getXml();
xml = replaceXmlValue(xml, "client-name", clientName);
xml = replaceXmlValue(xml, "guest-network-cidr", guestNetworkCidr);
xml = replaceXmlValue(xml, "ipsec-vpn-name", ipsecVpnName);
xml = replaceXmlValue(xml, "username", username);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add dynamic VPN client: " + clientName);
} else {
return true;
}
case DELETE:
if (!manageDynamicVpnClient(SrxCommand.CHECK_IF_EXISTS, clientName, accountId, guestNetworkCidr, ipsecVpnName, username)) {
return true;
}
xml = SrxXml.DYNAMIC_VPN_CLIENT_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "client-name", clientName);
if (!sendRequestAndCheckResponse(command, xml, "name", clientName)) {
throw new ExecutionException("Failed to delete dynamic VPN client: " + clientName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private String genAddressPoolName(long accountId) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId));
}
private boolean manageAddressPool(SrxCommand command, String addressPoolName, Long accountId, String guestNetworkCidr, String lowAddress, String highAddress,
String primaryDnsAddress) throws ExecutionException {
if (addressPoolName == null) {
addressPoolName = genAddressPoolName(accountId);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.ADDRESS_POOL_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "address-pool-name", addressPoolName);
return sendRequestAndCheckResponse(command, xml, "name", addressPoolName);
case ADD:
if (manageAddressPool(SrxCommand.CHECK_IF_EXISTS, addressPoolName, accountId, guestNetworkCidr, lowAddress, highAddress, primaryDnsAddress)) {
return true;
}
xml = SrxXml.ADDRESS_POOL_ADD.getXml();
xml = replaceXmlValue(xml, "address-pool-name", addressPoolName);
xml = replaceXmlValue(xml, "guest-network-cidr", guestNetworkCidr);
xml = replaceXmlValue(xml, "address-range-name", "r-" + addressPoolName);
xml = replaceXmlValue(xml, "low-address", lowAddress);
xml = replaceXmlValue(xml, "high-address", highAddress);
xml = replaceXmlValue(xml, "primary-dns-address", primaryDnsAddress);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add address pool: " + addressPoolName);
} else {
return true;
}
case DELETE:
if (!manageAddressPool(SrxCommand.CHECK_IF_EXISTS, addressPoolName, accountId, guestNetworkCidr, lowAddress, highAddress, primaryDnsAddress)) {
return true;
}
xml = SrxXml.ADDRESS_POOL_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "address-pool-name", addressPoolName);
if (!sendRequestAndCheckResponse(command, xml, "name", addressPoolName)) {
throw new ExecutionException("Failed to delete address pool: " + addressPoolName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private String genAccessProfileName(long accountId, String username) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId), username);
}
private boolean manageAccessProfile(SrxCommand command, String accessProfileName, Long accountId, String username, String password, String addressPoolName)
throws ExecutionException {
if (accessProfileName == null) {
accessProfileName = genAccessProfileName(accountId, username);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.ACCESS_PROFILE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "access-profile-name", accessProfileName);
return sendRequestAndCheckResponse(command, xml, "name", username);
case ADD:
if (manageAccessProfile(SrxCommand.CHECK_IF_EXISTS, accessProfileName, accountId, username, password, addressPoolName)) {
return true;
}
xml = SrxXml.ACCESS_PROFILE_ADD.getXml();
xml = replaceXmlValue(xml, "access-profile-name", accessProfileName);
xml = replaceXmlValue(xml, "username", username);
xml = replaceXmlValue(xml, "password", password);
xml = replaceXmlValue(xml, "address-pool-name", addressPoolName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add access profile: " + accessProfileName);
} else {
return true;
}
case DELETE:
if (!manageAccessProfile(SrxCommand.CHECK_IF_EXISTS, accessProfileName, accountId, username, password, addressPoolName)) {
return true;
}
xml = SrxXml.ACCESS_PROFILE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "access-profile-name", accessProfileName);
if (!sendRequestAndCheckResponse(command, xml, "name", username)) {
throw new ExecutionException("Failed to delete access profile: " + accessProfileName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
/*
* Private interfaces
*/
private boolean managePrivateInterface(SrxCommand command, boolean addFilters, long vlanTag, String privateInterfaceIp) throws ExecutionException {
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.PRIVATE_INTERFACE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "private-interface-name", _privateInterface);
xml = replaceXmlValue(xml, "vlan-id", String.valueOf(vlanTag));
return sendRequestAndCheckResponse(command, xml, "name", String.valueOf(vlanTag));
case ADD:
if (managePrivateInterface(SrxCommand.CHECK_IF_EXISTS, false, vlanTag, privateInterfaceIp)) {
return true;
}
xml = addFilters ? SrxXml.PRIVATE_INTERFACE_WITH_FILTERS_ADD.getXml() : SrxXml.PRIVATE_INTERFACE_ADD.getXml();
xml = replaceXmlValue(xml, "private-interface-name", _privateInterface);
xml = replaceXmlValue(xml, "vlan-id", String.valueOf(vlanTag));
xml = replaceXmlValue(xml, "private-interface-ip", privateInterfaceIp);
if (addFilters) {
xml = replaceXmlValue(xml, "input-filter-name", _usageFilterVlanInput.getName() + "-" + vlanTag);
xml = replaceXmlValue(xml, "output-filter-name", _usageFilterVlanOutput.getName() + "-" + vlanTag);
}
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add private interface for guest VLAN tag " + vlanTag);
} else {
return true;
}
case DELETE:
if (!managePrivateInterface(SrxCommand.CHECK_IF_EXISTS, false, vlanTag, privateInterfaceIp)) {
return true;
}
xml = SrxXml.PRIVATE_INTERFACE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "private-interface-name", _privateInterface);
xml = replaceXmlValue(xml, "vlan-id", String.valueOf(vlanTag));
if (!sendRequestAndCheckResponse(command, xml, "name", String.valueOf(vlanTag))) {
throw new ExecutionException("Failed to delete private interface for guest VLAN tag " + vlanTag);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private Long getVlanTagFromInterfaceName(String interfaceName) throws ExecutionException {
Long vlanTag = null;
if (interfaceName.contains(".")) {
try {
String unitNum = interfaceName.split("\\.")[1];
if (!unitNum.equals("0")) {
vlanTag = Long.parseLong(unitNum);
}
} catch (Exception e) {
s_logger.error(e);
throw new ExecutionException("Unable to parse VLAN tag from interface name: " + interfaceName);
}
}
return vlanTag;
}
/*
* Proxy ARP
*/
private boolean manageProxyArp(SrxCommand command, Long publicVlanTag, String publicIp) throws ExecutionException {
String publicInterface = genPublicInterface(publicVlanTag);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.PROXY_ARP_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "public-interface-name", publicInterface);
xml = replaceXmlValue(xml, "public-ip-address", publicIp);
return sendRequestAndCheckResponse(command, xml, "name", publicIp + "/32");
case CHECK_IF_IN_USE:
// Check if any NAT rules are using this proxy ARP entry
String poolName = genSourceNatPoolName(publicIp);
String allStaticNatRules = sendRequest(SrxXml.STATIC_NAT_RULE_GETALL.getXml());
String allDestNatRules = sendRequest(replaceXmlValue(SrxXml.DEST_NAT_RULE_GETALL.getXml(), "rule-set", _publicZone));
String allSrcNatRules = sendRequest(SrxXml.SRC_NAT_RULE_GETALL.getXml());
return (allStaticNatRules.contains(publicIp) || allDestNatRules.contains(publicIp) || allSrcNatRules.contains(poolName));
case ADD:
if (manageProxyArp(SrxCommand.CHECK_IF_EXISTS, publicVlanTag, publicIp)) {
return true;
}
xml = SrxXml.PROXY_ARP_ADD.getXml();
xml = replaceXmlValue(xml, "public-interface-name", publicInterface);
xml = replaceXmlValue(xml, "public-ip-address", publicIp);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add proxy ARP entry for public IP " + publicIp);
} else {
return true;
}
case DELETE:
if (!manageProxyArp(SrxCommand.CHECK_IF_EXISTS, publicVlanTag, publicIp)) {
return true;
}
if (manageProxyArp(SrxCommand.CHECK_IF_IN_USE, publicVlanTag, publicIp)) {
return true;
}
xml = SrxXml.PROXY_ARP_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "public-interface-name", publicInterface);
xml = replaceXmlValue(xml, "public-ip-address", publicIp);
if (!sendRequestAndCheckResponse(command, xml, "name", publicIp)) {
throw new ExecutionException("Failed to delete proxy ARP entry for public IP " + publicIp);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private Map<String, Long> getPublicVlanTagsForPublicIps(List<String> publicIps) throws ExecutionException {
Map<String, Long> publicVlanTags = new HashMap<String, Long>();
List<String> interfaceNames = new ArrayList<String>();
String xmlRequest = SrxXml.PROXY_ARP_GETALL.getXml();
xmlRequest = replaceXmlValue(xmlRequest, "interface-name", "");
String xmlResponse = sendRequest(xmlRequest);
Document doc = getDocument(xmlResponse);
NodeList interfaces = doc.getElementsByTagName("interface");
for (int i = 0; i < interfaces.getLength(); i++) {
String interfaceName = null;
NodeList interfaceEntries = interfaces.item(i).getChildNodes();
for (int j = 0; j < interfaceEntries.getLength(); j++) {
Node interfaceEntry = interfaceEntries.item(j);
if (interfaceEntry.getNodeName().equals("name")) {
interfaceName = interfaceEntry.getFirstChild().getNodeValue();
break;
}
}
if (interfaceName != null) {
interfaceNames.add(interfaceName);
}
}
if (interfaceNames.size() == 1) {
populatePublicVlanTagsMap(xmlResponse, interfaceNames.get(0), publicIps, publicVlanTags);
} else if (interfaceNames.size() > 1) {
for (String interfaceName : interfaceNames) {
xmlRequest = SrxXml.PROXY_ARP_GETALL.getXml();
xmlRequest = replaceXmlValue(xmlRequest, "interface-name", interfaceName);
xmlResponse = sendRequest(xmlRequest);
populatePublicVlanTagsMap(xmlResponse, interfaceName, publicIps, publicVlanTags);
}
}
return publicVlanTags;
}
private void populatePublicVlanTagsMap(String xmlResponse, String interfaceName, List<String> publicIps, Map<String, Long> publicVlanTags) throws ExecutionException {
Long publicVlanTag = getVlanTagFromInterfaceName(interfaceName);
if (publicVlanTag != null) {
for (String publicIp : publicIps) {
if (xmlResponse.contains(publicIp)) {
publicVlanTags.put(publicIp, publicVlanTag);
}
}
}
}
private Map<String, Long> getPublicVlanTagsForNatRules(List<String[]> natRules) throws ExecutionException {
List<String> publicIps = new ArrayList<String>();
addPublicIpsToList(natRules, publicIps);
return getPublicVlanTagsForPublicIps(publicIps);
}
private void addPublicIpsToList(List<String[]> natRules, List<String> publicIps) {
for (String[] natRule : natRules) {
if (!publicIps.contains(natRule[0])) {
publicIps.add(natRule[0]);
}
}
}
private String genPublicInterface(Long vlanTag) {
String publicInterface = _publicInterface;
if (!publicInterface.contains(".")) {
if (vlanTag == null) {
publicInterface += ".0";
} else {
publicInterface += "." + vlanTag;
}
}
return publicInterface;
}
/*
* Zone interfaces
*/
private String genZoneInterfaceName(long vlanTag) {
return _privateInterface + "." + String.valueOf(vlanTag);
}
private boolean manageZoneInterface(SrxCommand command, long vlanTag) throws ExecutionException {
String zoneInterfaceName = genZoneInterfaceName(vlanTag);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.ZONE_INTERFACE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "private-zone-name", _privateZone);
xml = replaceXmlValue(xml, "zone-interface-name", zoneInterfaceName);
return sendRequestAndCheckResponse(command, xml, "name", zoneInterfaceName);
case ADD:
if (manageZoneInterface(SrxCommand.CHECK_IF_EXISTS, vlanTag)) {
return true;
}
xml = SrxXml.ZONE_INTERFACE_ADD.getXml();
xml = replaceXmlValue(xml, "private-zone-name", _privateZone);
xml = replaceXmlValue(xml, "zone-interface-name", zoneInterfaceName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add interface " + zoneInterfaceName + " to zone " + _privateZone);
} else {
return true;
}
case DELETE:
if (!manageZoneInterface(SrxCommand.CHECK_IF_EXISTS, vlanTag)) {
return true;
}
xml = SrxXml.ZONE_INTERFACE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "private-zone-name", _privateZone);
xml = replaceXmlValue(xml, "zone-interface-name", zoneInterfaceName);
if (!sendRequestAndCheckResponse(command, xml, "name", zoneInterfaceName)) {
throw new ExecutionException("Failed to delete interface " + zoneInterfaceName + " from zone " + _privateZone);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
/*
* Static NAT rules
*/
private String genStaticNatRuleName(String publicIp, String privateIp) {
return genObjectName(genIpIdentifier(publicIp), genIpIdentifier(privateIp));
}
private boolean manageStaticNatRule(SrxCommand command, String publicIp, String privateIp) throws ExecutionException {
String ruleName = genStaticNatRuleName(publicIp, privateIp);
String ruleName_private = genStaticNatRuleName(privateIp, publicIp);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.STATIC_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "rule-set", _publicZone);
xml = replaceXmlValue(xml, "from-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
return sendRequestAndCheckResponse(command, xml, "name", ruleName);
case CHECK_PRIVATE_IF_EXISTS:
xml = SrxXml.STATIC_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName_private);
return sendRequestAndCheckResponse(command, xml, "name", ruleName_private);
case ADD:
if (manageStaticNatRule(SrxCommand.CHECK_IF_EXISTS, publicIp, privateIp)) {
return true;
}
xml = SrxXml.STATIC_NAT_RULE_ADD.getXml();
xml = replaceXmlValue(xml, "rule-set", _publicZone);
xml = replaceXmlValue(xml, "from-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
xml = replaceXmlValue(xml, "original-ip", publicIp);
xml = replaceXmlValue(xml, "translated-ip", privateIp);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add static NAT rule from public IP " + publicIp + " to private IP " + privateIp);
} else {
xml = SrxXml.STATIC_NAT_RULE_ADD.getXml();
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName_private);
xml = replaceXmlValue(xml, "original-ip", publicIp);
xml = replaceXmlValue(xml, "translated-ip", privateIp);
if (!sendRequestAndCheckResponse(command, xml))
{
throw new ExecutionException("Failed to add trust static NAT rule from public IP " + publicIp + " to private IP " + privateIp);
}
return true;
}
case DELETE:
if (!manageStaticNatRule(SrxCommand.CHECK_IF_EXISTS, publicIp, privateIp)) {
return true;
}
xml = SrxXml.STATIC_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "rule-set", _publicZone);
xml = replaceXmlValue(xml, "from-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
if (!sendRequestAndCheckResponse(command, xml, "name", ruleName)) {
throw new ExecutionException("Failed to delete static NAT rule from public IP " + publicIp + " to private IP " + privateIp);
} else {
if (manageStaticNatRule(SrxCommand.CHECK_PRIVATE_IF_EXISTS, publicIp, privateIp)){
xml = SrxXml.STATIC_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName_private);
if (!sendRequestAndCheckResponse(command, xml, "name", ruleName_private))
{
throw new ExecutionException("Failed to delete trust static NAT rule from public IP " + publicIp + " to private IP " + privateIp);
}
}
return true;
}
default:
throw new ExecutionException("Unrecognized command.");
}
}
private List<String[]> getStaticNatRules(RuleMatchCondition condition, String privateGateway, Long privateCidrSize) throws ExecutionException {
List<String[]> staticNatRules = new ArrayList<String[]>();
String xmlRequest = SrxXml.STATIC_NAT_RULE_GETALL.getXml();
String xmlResponse = sendRequest(xmlRequest);
Document doc = getDocument(xmlResponse);
NodeList rules = doc.getElementsByTagName("rule");
for (int i = 0; i < rules.getLength(); i++) {
NodeList ruleEntries = rules.item(i).getChildNodes();
for (int j = 0; j < ruleEntries.getLength(); j++) {
Node ruleEntry = ruleEntries.item(j);
if (ruleEntry.getNodeName().equals("name")) {
String name = ruleEntry.getFirstChild().getNodeValue();
String[] nameContents = name.split("-");
if (nameContents.length != 8) {
continue;
}
String rulePublicIp = nameContents[0] + "." + nameContents[1] + "." + nameContents[2] + "." + nameContents[3];
String rulePrivateIp = nameContents[4] + "." + nameContents[5] + "." + nameContents[6] + "." + nameContents[7];
boolean addToList = false;
if (condition.equals(RuleMatchCondition.ALL)) {
addToList = true;
} else if (condition.equals(RuleMatchCondition.PRIVATE_SUBNET)) {
assert (privateGateway != null && privateCidrSize != null);
addToList = NetUtils.sameSubnetCIDR(rulePrivateIp, privateGateway, privateCidrSize);
} else {
s_logger.error("Invalid rule match condition.");
assert false;
}
if (addToList) {
staticNatRules.add(new String[] {rulePublicIp, rulePrivateIp});
}
}
}
}
return staticNatRules;
}
/*
* Destination NAT pools
*/
private String genDestinationNatPoolName(String privateIp, long destPort) {
return genObjectName(genIpIdentifier(privateIp), String.valueOf(destPort));
}
private boolean manageDestinationNatPool(SrxCommand command, String privateIp, long destPort) throws ExecutionException {
String poolName = genDestinationNatPoolName(privateIp, destPort);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.DEST_NAT_POOL_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "pool-name", poolName);
return sendRequestAndCheckResponse(command, xml, "name", poolName);
case CHECK_IF_IN_USE:
// Check if any destination nat rules refer to this pool
xml = SrxXml.DEST_NAT_RULE_GETALL.getXml();
xml = replaceXmlValue(xml, "rule-set", _publicZone);
return sendRequestAndCheckResponse(command, xml, "pool-name", poolName);
case ADD:
if (manageDestinationNatPool(SrxCommand.CHECK_IF_EXISTS, privateIp, destPort)) {
return true;
}
xml = SrxXml.DEST_NAT_POOL_ADD.getXml();
xml = replaceXmlValue(xml, "pool-name", poolName);
xml = replaceXmlValue(xml, "private-address", privateIp + "/32");
xml = replaceXmlValue(xml, "dest-port", String.valueOf(destPort));
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add destination NAT pool for private IP " + privateIp + " and private port " + destPort);
} else {
return true;
}
case DELETE:
if (!manageDestinationNatPool(SrxCommand.CHECK_IF_EXISTS, privateIp, destPort)) {
return true;
}
if (manageDestinationNatPool(SrxCommand.CHECK_IF_IN_USE, privateIp, destPort)) {
return true;
}
xml = SrxXml.DEST_NAT_POOL_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "pool-name", poolName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete destination NAT pool for private IP " + privateIp + " and private port " + destPort);
} else {
return true;
}
default:
throw new ExecutionException("Unrecognized command.");
}
}
/*
* Destination NAT rules
*/
private String genDestinationNatRuleName(String publicIp, String privateIp, long srcPort, long destPort) {
return "destnatrule-" +
String.valueOf(genObjectName(publicIp, privateIp, String.valueOf(srcPort), String.valueOf(destPort)).hashCode()).replaceAll("[^a-zA-Z0-9]", "");
}
private boolean manageDestinationNatRule(SrxCommand command, String publicIp, String privateIp, long srcPort, long destPort) throws ExecutionException {
String ruleName = genDestinationNatRuleName(publicIp, privateIp, srcPort, destPort);
String ruleName_private = ruleName + "p";
String poolName = genDestinationNatPoolName(privateIp, destPort);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.DEST_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "rule-set", _publicZone);
xml = replaceXmlValue(xml, "from-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
return sendRequestAndCheckResponse(command, xml, "name", ruleName);
case CHECK_PRIVATE_IF_EXISTS:
xml = SrxXml.DEST_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName_private);
return sendRequestAndCheckResponse(command, xml, "name", ruleName_private);
case ADD:
if (manageDestinationNatRule(SrxCommand.CHECK_IF_EXISTS, publicIp, privateIp, srcPort, destPort)) {
return true;
}
if (!manageDestinationNatPool(SrxCommand.CHECK_IF_EXISTS, privateIp, destPort)) {
throw new ExecutionException("The destination NAT pool corresponding to private IP: " + privateIp + " and destination port: " + destPort +
" does not exist.");
}
xml = SrxXml.DEST_NAT_RULE_ADD.getXml();
xml = replaceXmlValue(xml, "rule-set", _publicZone);
xml = replaceXmlValue(xml, "from-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
xml = replaceXmlValue(xml, "public-address", publicIp);
xml = replaceXmlValue(xml, "src-port", String.valueOf(srcPort));
xml = replaceXmlValue(xml, "pool-name", poolName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add destination NAT rule from public IP " + publicIp + ", public port " + srcPort + ", private IP " +
privateIp + ", and private port " + destPort);
} else {
xml = SrxXml.DEST_NAT_RULE_ADD.getXml();
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName_private);
xml = replaceXmlValue(xml, "public-address", publicIp);
xml = replaceXmlValue(xml, "src-port", String.valueOf(srcPort));
xml = replaceXmlValue(xml, "pool-name", poolName);
if (!sendRequestAndCheckResponse(command, xml))
{
s_logger.debug("Purple: loopback Failed to add " + _privateZone + " destination NAT rule from public IP " + publicIp + ", public port " + srcPort + ", private IP " +
privateIp + ", and private port " + destPort);
}
return true;
}
case DELETE:
if (!manageDestinationNatRule(SrxCommand.CHECK_IF_EXISTS, publicIp, privateIp, srcPort, destPort)) {
return true;
}
xml = SrxXml.DEST_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "rule-set", _publicZone);
xml = replaceXmlValue(xml, "from-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete destination NAT rule from public IP " + publicIp + ", public port " + srcPort + ", private IP " +
privateIp + ", and private port " + destPort);
} else {
if (manageDestinationNatRule(SrxCommand.CHECK_PRIVATE_IF_EXISTS, publicIp, privateIp, srcPort, destPort))
{
xml = SrxXml.DEST_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName_private);
if (!sendRequestAndCheckResponse(command, xml))
{
s_logger.debug("Purple: Failed to delete " + _privateZone + " destination NAT rule from public IP " + publicIp + ", public port " + srcPort + ", private IP " +
privateIp + ", and private port " + destPort);
}
}
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private List<String[]> getDestNatRules(RuleMatchCondition condition, String publicIp, String privateIp, String privateGateway, Long privateCidrSize)
throws ExecutionException {
List<String[]> destNatRules = new ArrayList<String[]>();
String xmlRequest = SrxXml.DEST_NAT_RULE_GETALL.getXml();
xmlRequest = replaceXmlValue(xmlRequest, "rule-set", _publicZone);
String xmlResponse = sendRequest(xmlRequest);
Document doc = getDocument(xmlResponse);
NodeList rules = doc.getElementsByTagName("rule");
for (int ruleIndex = 0; ruleIndex < rules.getLength(); ruleIndex++) {
String rulePublicIp = null;
String rulePrivateIp = null;
String ruleSrcPort = null;
String ruleDestPort = null;
NodeList ruleEntries = rules.item(ruleIndex).getChildNodes();
for (int ruleEntryIndex = 0; ruleEntryIndex < ruleEntries.getLength(); ruleEntryIndex++) {
Node ruleEntry = ruleEntries.item(ruleEntryIndex);
if (ruleEntry.getNodeName().equals("dest-nat-rule-match")) {
NodeList ruleMatchEntries = ruleEntry.getChildNodes();
for (int ruleMatchIndex = 0; ruleMatchIndex < ruleMatchEntries.getLength(); ruleMatchIndex++) {
Node ruleMatchEntry = ruleMatchEntries.item(ruleMatchIndex);
if (ruleMatchEntry.getNodeName().equals("destination-address")) {
NodeList destAddressEntries = ruleMatchEntry.getChildNodes();
for (int destAddressIndex = 0; destAddressIndex < destAddressEntries.getLength(); destAddressIndex++) {
Node destAddressEntry = destAddressEntries.item(destAddressIndex);
if (destAddressEntry.getNodeName().equals("dst-addr")) {
rulePublicIp = destAddressEntry.getFirstChild().getNodeValue().split("/")[0];
}
}
} else if (ruleMatchEntry.getNodeName().equals("destination-port")) {
NodeList destPortEntries = ruleMatchEntry.getChildNodes();
for (int destPortIndex = 0; destPortIndex < destPortEntries.getLength(); destPortIndex++) {
Node destPortEntry = destPortEntries.item(destPortIndex);
if (destPortEntry.getNodeName().equals("dst-port")) {
ruleSrcPort = destPortEntry.getFirstChild().getNodeValue();
}
}
}
}
} else if (ruleEntry.getNodeName().equals("then")) {
NodeList ruleThenEntries = ruleEntry.getChildNodes();
for (int ruleThenIndex = 0; ruleThenIndex < ruleThenEntries.getLength(); ruleThenIndex++) {
Node ruleThenEntry = ruleThenEntries.item(ruleThenIndex);
if (ruleThenEntry.getNodeName().equals("destination-nat")) {
NodeList destNatEntries = ruleThenEntry.getChildNodes();
for (int destNatIndex = 0; destNatIndex < destNatEntries.getLength(); destNatIndex++) {
Node destNatEntry = destNatEntries.item(destNatIndex);
if (destNatEntry.getNodeName().equals("pool")) {
NodeList poolEntries = destNatEntry.getChildNodes();
for (int poolIndex = 0; poolIndex < poolEntries.getLength(); poolIndex++) {
Node poolEntry = poolEntries.item(poolIndex);
if (poolEntry.getNodeName().equals("pool-name")) {
String[] poolName = poolEntry.getFirstChild().getNodeValue().split("-");
if (poolName.length == 5) {
rulePrivateIp = poolName[0] + "." + poolName[1] + "." + poolName[2] + "." + poolName[3];
ruleDestPort = poolName[4];
}
}
}
}
}
}
}
}
}
if (rulePublicIp == null || rulePrivateIp == null || ruleSrcPort == null || ruleDestPort == null) {
continue;
}
boolean addToList = false;
if (condition.equals(RuleMatchCondition.ALL)) {
addToList = true;
} else if (condition.equals(RuleMatchCondition.PUBLIC_PRIVATE_IPS)) {
assert (publicIp != null && privateIp != null);
addToList = publicIp.equals(rulePublicIp) && privateIp.equals(rulePrivateIp);
} else if (condition.equals(RuleMatchCondition.PRIVATE_SUBNET)) {
assert (privateGateway != null && privateCidrSize != null);
addToList = NetUtils.sameSubnetCIDR(rulePrivateIp, privateGateway, privateCidrSize);
}
if (addToList) {
destNatRules.add(new String[] {rulePublicIp, rulePrivateIp, ruleSrcPort, ruleDestPort});
}
}
return destNatRules;
}
/*
* Source NAT pools
*/
private String genSourceNatPoolName(String publicIp) {
return genObjectName(genIpIdentifier(publicIp));
}
private boolean manageSourceNatPool(SrxCommand command, String publicIp) throws ExecutionException {
String poolName = genSourceNatPoolName(publicIp);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.SRC_NAT_POOL_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "pool-name", poolName);
return sendRequestAndCheckResponse(command, xml, "name", poolName);
case CHECK_IF_IN_USE:
// Check if any source nat rules refer to this pool
xml = SrxXml.SRC_NAT_RULE_GETALL.getXml();
return sendRequestAndCheckResponse(command, xml, "pool-name", poolName);
case ADD:
if (manageSourceNatPool(SrxCommand.CHECK_IF_EXISTS, publicIp)) {
return true;
}
xml = SrxXml.SRC_NAT_POOL_ADD.getXml();
xml = replaceXmlValue(xml, "pool-name", poolName);
xml = replaceXmlValue(xml, "address", publicIp + "/32");
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add source NAT pool for public IP " + publicIp);
} else {
return true;
}
case DELETE:
if (!manageSourceNatPool(SrxCommand.CHECK_IF_EXISTS, publicIp)) {
return true;
}
if (manageSourceNatPool(SrxCommand.CHECK_IF_IN_USE, publicIp)) {
return true;
}
xml = SrxXml.SRC_NAT_POOL_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "pool-name", poolName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete source NAT pool for public IP " + publicIp);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
/*
* Source NAT rules
*/
private String genSourceNatRuleName(String publicIp, String privateSubnet) {
return genObjectName(genIpIdentifier(publicIp), genIpIdentifier(privateSubnet));
}
private boolean manageSourceNatRule(SrxCommand command, String publicIp, String privateSubnet) throws ExecutionException {
String ruleName = genSourceNatRuleName(publicIp, privateSubnet);
String poolName = genSourceNatPoolName(publicIp);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.SRC_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
return sendRequestAndCheckResponse(command, xml, "name", ruleName);
case ADD:
if (manageSourceNatRule(SrxCommand.CHECK_IF_EXISTS, publicIp, privateSubnet)) {
return true;
}
if (!manageSourceNatPool(SrxCommand.CHECK_IF_EXISTS, publicIp)) {
throw new ExecutionException("The source NAT pool corresponding to " + publicIp + " does not exist.");
}
xml = SrxXml.SRC_NAT_RULE_ADD.getXml();
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "to-zone", _publicZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
xml = replaceXmlValue(xml, "private-subnet", privateSubnet);
xml = replaceXmlValue(xml, "pool-name", poolName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add source NAT rule for public IP " + publicIp + " and private subnet " + privateSubnet);
} else {
return true;
}
case DELETE:
if (!manageSourceNatRule(SrxCommand.CHECK_IF_EXISTS, publicIp, privateSubnet)) {
return true;
}
xml = SrxXml.SRC_NAT_RULE_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "rule-set", _privateZone);
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "rule-name", ruleName);
if (!sendRequestAndCheckResponse(command, xml, "name", ruleName)) {
throw new ExecutionException("Failed to delete source NAT rule for public IP " + publicIp + " and private subnet " + privateSubnet);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
/*
* Address book entries
*/
private String genAddressBookEntryName(String ip) {
if (ip == null) {
return "any";
} else {
return genIpIdentifier(ip);
}
}
private boolean manageAddressBookEntry(SrxCommand command, String zone, String ip, String entryName) throws ExecutionException {
if (!zone.equals(_publicZone) && !zone.equals(_privateZone)) {
throw new ExecutionException("Invalid zone.");
}
if (entryName == null) {
entryName = genAddressBookEntryName(ip);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.ADDRESS_BOOK_ENTRY_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "zone", zone);
xml = replaceXmlValue(xml, "entry-name", entryName);
return sendRequestAndCheckResponse(command, xml, "name", entryName);
case CHECK_IF_IN_USE:
// Check if any security policies refer to this address book entry
xml = SrxXml.SECURITY_POLICY_GETALL.getXml();
String fromZone = zone.equals(_publicZone) ? _privateZone : _publicZone;
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", zone);
return sendRequestAndCheckResponse(command, xml, "destination-address", entryName);
case ADD:
if (manageAddressBookEntry(SrxCommand.CHECK_IF_EXISTS, zone, ip, entryName)) {
return true;
}
xml = SrxXml.ADDRESS_BOOK_ENTRY_ADD.getXml();
xml = replaceXmlValue(xml, "zone", zone);
xml = replaceXmlValue(xml, "entry-name", entryName);
xml = replaceXmlValue(xml, "ip", ip);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add address book entry for IP " + ip + " in zone " + zone);
} else {
return true;
}
case DELETE:
if (!manageAddressBookEntry(SrxCommand.CHECK_IF_EXISTS, zone, ip, entryName)) {
return true;
}
if (manageAddressBookEntry(SrxCommand.CHECK_IF_IN_USE, zone, ip, entryName)) {
return true;
}
xml = SrxXml.ADDRESS_BOOK_ENTRY_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "zone", zone);
xml = replaceXmlValue(xml, "entry-name", entryName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete address book entry for IP " + ip + " in zone " + zone);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
/*
* Applications
*/
private String genApplicationName(SecurityPolicyType type, Protocol protocol, int startPort, int endPort) {
if (protocol.equals(Protocol.any)) {
return Protocol.any.toString();
} else {
if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS) || type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT)) {
return genObjectName(type.getIdentifier(), protocol.toString(), String.valueOf(startPort), String.valueOf(endPort));
} else {
return genObjectName(protocol.toString(), String.valueOf(startPort), String.valueOf(endPort));
}
}
}
private Object[] parseApplicationName(SecurityPolicyType type, String applicationName) throws ExecutionException {
String errorMsg = "Invalid application: " + applicationName;
String[] applicationComponents = applicationName.split("-");
Protocol protocol;
Integer startPort;
Integer endPort;
int offset = 0;
try {
offset = (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS) || type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT)) ? 1 : 0;
protocol = getProtocol(applicationComponents[offset + 0]);
startPort = Integer.parseInt(applicationComponents[offset + 1]);
endPort = Integer.parseInt(applicationComponents[offset + 2]);
} catch (Exception e) {
throw new ExecutionException(errorMsg);
}
return new Object[] {protocol, startPort, endPort};
}
private boolean manageApplication(SecurityPolicyType type, SrxCommand command, Protocol protocol, int startPort, int endPort) throws ExecutionException {
if (protocol.equals(Protocol.any)) {
return true;
}
String applicationName = genApplicationName(type, protocol, startPort, endPort);
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.APPLICATION_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "name", applicationName);
return sendRequestAndCheckResponse(command, xml, "name", applicationName);
case ADD:
if (manageApplication(type, SrxCommand.CHECK_IF_EXISTS, protocol, startPort, endPort)) {
return true;
}
String icmpOrDestPort;
xml = SrxXml.APPLICATION_ADD.getXml();
xml = replaceXmlValue(xml, "name", applicationName);
xml = replaceXmlValue(xml, "protocol", protocol.toString());
if (protocol.toString().equals(Protocol.icmp.toString())) {
icmpOrDestPort = "<icmp-type>" + startPort + "</icmp-type>";
icmpOrDestPort += "<icmp-code>" + endPort + "</icmp-code>";
} else {
String destPort;
if (startPort == endPort) {
destPort = String.valueOf(startPort);
} else {
destPort = startPort + "-" + endPort;
}
icmpOrDestPort = "<destination-port>" + destPort + "</destination-port>";
}
xml = replaceXmlValue(xml, "dest-port-icmp", icmpOrDestPort);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add application " + applicationName);
} else {
return true;
}
case DELETE:
if (!manageApplication(type, SrxCommand.CHECK_IF_EXISTS, protocol, startPort, endPort)) {
return true;
}
xml = SrxXml.APPLICATION_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "name", applicationName);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete application " + applicationName);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private List<String> getUnusedApplications(List<String> applications, String fromZone, String toZone) throws ExecutionException {
List<String> unusedApplications = new ArrayList<String>();
// Check if any of the applications are unused by existing security policies
String xml = SrxXml.SECURITY_POLICY_GETALL.getXml();
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
String allPolicies = sendRequest(xml);
for (String application : applications) {
if (!application.equals(Protocol.any.toString()) && !allPolicies.contains(application)) {
unusedApplications.add(application);
}
}
return unusedApplications;
}
private List<String> getApplicationsForSecurityPolicy(SecurityPolicyType type, String privateIp, String fromZone, String toZone) throws ExecutionException {
String policyName = genSecurityPolicyName(type, null, null, fromZone, toZone, privateIp);
String xml = SrxXml.SECURITY_POLICY_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
xml = replaceXmlValue(xml, "policy-name", policyName);
String policy = sendRequest(xml);
Document doc = getDocument(policy);
List<String> policyApplications = new ArrayList<String>();
NodeList applicationNodes = doc.getElementsByTagName("application");
for (int i = 0; i < applicationNodes.getLength(); i++) {
Node applicationNode = applicationNodes.item(i);
policyApplications.add(applicationNode.getFirstChild().getNodeValue());
}
return policyApplications;
}
private List<Object[]> extractApplications(List<FirewallRuleTO> rules) throws ExecutionException {
List<Object[]> applications = new ArrayList<Object[]>();
for (FirewallRuleTO rule : rules) {
Object[] application = new Object[3];
application[0] = getProtocol(rule.getProtocol());
if (application[0] == Protocol.icmp) {
if (rule.getIcmpType() == -1) {
application[1] = 255;
} else {
application[1] = rule.getIcmpType();
}
if (rule.getIcmpCode() == -1) {
application[2] = 255;
} else {
application[2] = rule.getIcmpCode();
}
} else if (application[0] == Protocol.tcp || application[0] == Protocol.udp) {
if (rule.getSrcPortRange() != null) {
application[1] = rule.getSrcPortRange()[0];
application[2] = rule.getSrcPortRange()[1];
} else {
application[1] = 0;
application[2] = 65535;
}
} else if (application[0] == Protocol.all) {
application[1] = 0;
application[2] = 65535;
}
applications.add(application);
}
return applications;
}
/*
* Security policies
*/
private String genSecurityPolicyName(SecurityPolicyType type, Long accountId, String username, String fromZone, String toZone, String translatedIp) {
if (type.equals(SecurityPolicyType.VPN)) {
return genObjectName(_vpnObjectPrefix, String.valueOf(accountId), username);
} else {
return genObjectName(type.getIdentifier(), fromZone, toZone, genIpIdentifier(translatedIp));
}
}
private boolean manageSecurityPolicy(SecurityPolicyType type, SrxCommand command, Long accountId, String username, String privateIp, List<String> applicationNames,
List<String> cidrs, String ipsecVpnName, boolean defaultEgressAction) throws ExecutionException {
String fromZone = _publicZone;
String toZone = _privateZone;
String securityPolicyName;
String addressBookEntryName = null;
if (type.equals(SecurityPolicyType.VPN) && ipsecVpnName != null) {
securityPolicyName = ipsecVpnName;
addressBookEntryName = ipsecVpnName;
} else if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS) || type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT)) {
fromZone = _privateZone;
toZone = _publicZone;
securityPolicyName = genSecurityPolicyName(type, accountId, username, fromZone, toZone, privateIp);
} else {
securityPolicyName = genSecurityPolicyName(type, accountId, username, fromZone, toZone, privateIp);
addressBookEntryName = genAddressBookEntryName(privateIp);
}
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.SECURITY_POLICY_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
xml = replaceXmlValue(xml, "policy-name", securityPolicyName);
return sendRequestAndCheckResponse(command, xml, "name", securityPolicyName);
case CHECK_IF_IN_USE:
List<String[]> rulesToCheck = null;
if (type.equals(SecurityPolicyType.STATIC_NAT)) {
// Check if any static NAT rules rely on this security policy
rulesToCheck = getStaticNatRules(RuleMatchCondition.ALL, null, null);
} else if (type.equals(SecurityPolicyType.DESTINATION_NAT)) {
// Check if any destination NAT rules rely on this security policy
rulesToCheck = getDestNatRules(RuleMatchCondition.ALL, null, null, null, null);
} else {
return false;
}
for (String[] rule : rulesToCheck) {
String rulePrivateIp = rule[1];
if (privateIp.equals(rulePrivateIp)) {
return true;
}
}
return false;
case ADD:
if (!(type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS) || type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT))) {
if (!manageAddressBookEntry(SrxCommand.CHECK_IF_EXISTS, toZone, privateIp, addressBookEntryName)) {
throw new ExecutionException("No address book entry for policy: " + securityPolicyName);
}
}
String srcAddrs = "";
String dstAddrs = "";
String action = "";
xml = SrxXml.SECURITY_POLICY_ADD.getXml();
xml = replaceXmlValue(xml, "policy-name", securityPolicyName);
if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS) || type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT)) {
xml = replaceXmlValue(xml, "from-zone", _privateZone);
xml = replaceXmlValue(xml, "to-zone", _publicZone);
if (cidrs == null || cidrs.size() == 0) {
srcAddrs = "<source-address>any</source-address>";
} else {
for (String cidr : cidrs) {
srcAddrs += "<source-address>" + genAddressBookEntryName(cidr) + "</source-address>";
}
}
xml = replaceXmlValue(xml, "src-address", srcAddrs);
dstAddrs = "<destination-address>any</destination-address>";
xml = replaceXmlValue(xml, "dst-address", dstAddrs);
if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT)) {
if (defaultEgressAction == false) {
//for default policy is false add default deny rules
action = "<deny></deny>";
} else {
action = "<permit></permit>";
}
} else {
if (defaultEgressAction == true) {
//configure egress rules to deny the traffic when default egress is allow
action = "<deny></deny>";
} else {
action = "<permit></permit>";
}
}
xml = replaceXmlValue(xml, "action", action);
} else {
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
srcAddrs = "<source-address>any</source-address>";
xml = replaceXmlValue(xml, "src-address", srcAddrs);
dstAddrs = "<destination-address>" + addressBookEntryName + "</destination-address>";
xml = replaceXmlValue(xml, "dst-address", dstAddrs);
}
if (type.equals(SecurityPolicyType.VPN) && ipsecVpnName != null) {
xml = replaceXmlValue(xml, "tunnel", "<permit><tunnel><ipsec-vpn>" + ipsecVpnName + "</ipsec-vpn></tunnel></permit>");
} else {
xml = replaceXmlValue(xml, "tunnel", "");
if (!(type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS_DEFAULT) || type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS))) {
action = "<permit></permit>";
xml = replaceXmlValue(xml, "action", action);
}
}
String applications;
if (applicationNames == null || applicationNames.size() == 0) {
applications = "<application>any</application>";
} else {
applications = "";
for (String applicationName : applicationNames) {
applications += "<application>" + applicationName + "</application>";
}
}
xml = replaceXmlValue(xml, "applications", applications);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add security policy for privateIp " + privateIp + " and applications " + applicationNames);
} else {
return true;
}
case DELETE:
if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, privateIp, applicationNames, cidrs, ipsecVpnName, defaultEgressAction)) {
return true;
}
if (manageSecurityPolicy(type, SrxCommand.CHECK_IF_IN_USE, null, null, privateIp, applicationNames, cidrs, ipsecVpnName, defaultEgressAction)) {
return true;
}
xml = SrxXml.SECURITY_POLICY_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
xml = replaceXmlValue(xml, "policy-name", securityPolicyName);
boolean success = sendRequestAndCheckResponse(command, xml);
if (success) {
xml = SrxXml.SECURITY_POLICY_GETALL.getXml();
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
String getAllResponseXml = sendRequest(xml);
if (getAllResponseXml == null) {
throw new ExecutionException("Deleted security policy, but failed to delete security policy group.");
}
if (!getAllResponseXml.contains(fromZone) || !getAllResponseXml.contains(toZone)) {
return true;
} else if (!getAllResponseXml.contains("match") && !getAllResponseXml.contains("then")) {
xml = SrxXml.SECURITY_POLICY_GROUP.getXml();
xml = replaceXmlValue(xml, "from-zone", fromZone);
xml = replaceXmlValue(xml, "to-zone", toZone);
xml = setDelete(xml, true);
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Deleted security policy, but failed to delete security policy group.");
} else {
return true;
}
} else {
return true;
}
} else {
throw new ExecutionException("Failed to delete security policy for privateIp " + privateIp + " and applications " + applicationNames);
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private boolean addSecurityPolicyAndApplications(SecurityPolicyType type, String privateIp, List<Object[]> applications) throws ExecutionException {
// Add all necessary applications
List<String> applicationNames = new ArrayList<String>();
for (Object[] application : applications) {
Protocol protocol = (Protocol)application[0];
int startPort = application[1] != null ? ((Integer)application[1]) : -1;
int endPort = application[2] != null ? ((Integer)application[2]) : -1;
String applicationName = genApplicationName(type, protocol, startPort, endPort);
if (!applicationNames.contains(applicationName)) {
applicationNames.add(applicationName);
}
manageApplication(type, SrxCommand.ADD, protocol, startPort, endPort);
}
// Add a new security policy
manageSecurityPolicy(type, SrxCommand.ADD, null, null, privateIp, applicationNames, null, null, false);
return true;
}
private boolean removeSecurityPolicyAndApplications(SecurityPolicyType type, String privateIp) throws ExecutionException {
if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, privateIp, null, null, null, false)) {
return true;
}
if (manageSecurityPolicy(type, SrxCommand.CHECK_IF_IN_USE, null, null, privateIp, null, null, null, false)) {
return true;
}
// Get a list of applications for this security policy
List<String> applications = getApplicationsForSecurityPolicy(type, privateIp, _publicZone, _privateZone);
// Remove the security policy
manageSecurityPolicy(type, SrxCommand.DELETE, null, null, privateIp, null, null, null, false);
// Remove any applications for the removed security policy that are no longer in use
List<String> unusedApplications = getUnusedApplications(applications, _publicZone, _privateZone);
for (String application : unusedApplications) {
Object[] applicationComponents;
try {
applicationComponents = parseApplicationName(type, application);
} catch (ExecutionException e) {
s_logger.error("Found an invalid application: " + application + ". Not attempting to clean up.");
continue;
}
Protocol protocol = (Protocol)applicationComponents[0];
Integer startPort = (Integer)applicationComponents[1];
Integer endPort = (Integer)applicationComponents[2];
manageApplication(type, SrxCommand.DELETE, protocol, startPort, endPort);
}
return true;
}
private boolean removeEgressSecurityPolicyAndApplications(SecurityPolicyType type, String guestVlan, List<String> cidrs, boolean defaultEgressAction)
throws ExecutionException {
if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, guestVlan, null, cidrs, null, defaultEgressAction)) {
return true;
}
// Get a list of applications for this security policy
List<String> applications;
applications = getApplicationsForSecurityPolicy(type, guestVlan, _privateZone, _publicZone);
// Remove the security policy even if it is in use
manageSecurityPolicy(type, SrxCommand.DELETE, null, null, guestVlan, null, cidrs, null, defaultEgressAction);
// Remove any applications for the removed security policy that are no longer in use
List<String> unusedApplications;
unusedApplications = getUnusedApplications(applications, _privateZone, _publicZone);
for (String application : unusedApplications) {
Object[] applicationComponents;
try {
applicationComponents = parseApplicationName(type, application);
} catch (ExecutionException e) {
s_logger.error("Found an invalid application: " + application + ". Not attempting to clean up.");
continue;
}
Protocol protocol = (Protocol)applicationComponents[0];
Integer startPort = (Integer)applicationComponents[1];
Integer endPort = (Integer)applicationComponents[2];
manageApplication(type, SrxCommand.DELETE, protocol, startPort, endPort);
}
for (String cidr : cidrs) {
manageAddressBookEntry(SrxCommand.DELETE, _publicZone, cidr, null);
}
return true;
}
private boolean addEgressSecurityPolicyAndApplications(SecurityPolicyType type, String guestVlan, List<Object[]> applications, List<String> cidrs,
boolean defaultEgressAction) throws ExecutionException {
// Add all necessary applications
List<String> applicationNames = new ArrayList<String>();
for (Object[] application : applications) {
Protocol protocol = (Protocol)application[0];
if (!protocol.equals(Protocol.all)) {
int startPort = application[1] != null ? ((Integer)application[1]) : 0;
int endPort = application[2] != null ? ((Integer)application[2]) : 65535;
String applicationName = genApplicationName(type, protocol, startPort, endPort);
if (!applicationNames.contains(applicationName)) {
applicationNames.add(applicationName);
}
manageApplication(type, SrxCommand.ADD, protocol, startPort, endPort);
}
}
for (String cidr : cidrs) {
manageAddressBookEntry(SrxCommand.ADD, _privateZone, cidr, null);
}
// Add a new security policy
manageSecurityPolicy(type, SrxCommand.ADD, null, null, guestVlan, applicationNames, cidrs, null, defaultEgressAction);
s_logger.debug("Added Egress firewall rule for guest network " + guestVlan);
return true;
}
/*
* Filter terms
*/
private String genIpFilterTermName(String ipAddress) {
return genIpIdentifier(ipAddress);
}
private boolean manageUsageFilter(SrxCommand command, UsageFilter filter, String ip, Long guestVlanTag, String filterTermName) throws ExecutionException {
String filterName;
String filterDescription;
String xml;
if (filter.equals(_usageFilterIPInput) || filter.equals(_usageFilterIPOutput)) {
assert (ip != null && guestVlanTag == null);
filterName = filter.getName();
filterDescription = filter.toString() + ", public IP = " + ip;
xml = SrxXml.PUBLIC_IP_FILTER_TERM_ADD.getXml();
} else if (filter.equals(_usageFilterVlanInput) || filter.equals(_usageFilterVlanOutput)) {
assert (ip == null && guestVlanTag != null);
filterName = filter.getName() + "-" + guestVlanTag;
filterDescription = filter.toString() + ", guest VLAN tag = " + guestVlanTag;
filterTermName = filterName;
xml = SrxXml.GUEST_VLAN_FILTER_TERM_ADD.getXml();
} else {
return false;
}
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.FILTER_TERM_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "filter-name", filterName);
xml = replaceXmlValue(xml, "term-name", filterTermName);
return sendRequestAndCheckResponse(command, xml, "name", filterTermName);
case ADD:
if (manageUsageFilter(SrxCommand.CHECK_IF_EXISTS, filter, ip, guestVlanTag, filterTermName)) {
return true;
}
xml = replaceXmlValue(xml, "filter-name", filterName);
xml = replaceXmlValue(xml, "term-name", filterTermName);
if (filter.equals(_usageFilterIPInput) || filter.equals(_usageFilterIPOutput)) {
xml = replaceXmlValue(xml, "ip-address", ip);
xml = replaceXmlValue(xml, "address-type", filter.getAddressType());
}
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add usage filter: " + filterDescription);
} else {
return true;
}
case DELETE:
if (!manageUsageFilter(SrxCommand.CHECK_IF_EXISTS, filter, ip, guestVlanTag, filterTermName)) {
return true;
}
boolean deleteFilter = filter.equals(_usageFilterVlanInput) || filter.equals(_usageFilterVlanOutput);
xml = deleteFilter ? SrxXml.FILTER_GETONE.getXml() : SrxXml.FILTER_TERM_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "filter-name", filterName);
xml = !deleteFilter ? replaceXmlValue(xml, "term-name", filterTermName) : xml;
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete usage filter: " + filterDescription);
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
private String genNameValueEntry(String name, String value) {
String xml = SrxXml.TEMPLATE_ENTRY.getXml();
xml = replaceXmlValue(xml, "name", name);
xml = replaceXmlValue(xml, "value", value);
return xml;
}
private String genMultipleEntries(String name, List<String> values) {
String result = "";
for (String value : values) {
result = result + genNameValueEntry(name, value);
}
return result;
}
private String genPortRangeEntry(String protocol, String portRange) {
String result = "";
result = result + genNameValueEntry("protocol", protocol);
result = result + genNameValueEntry("destination-port", portRange);
return result;
}
private String genIcmpEntries(String icmpType, String icmpCode) {
String result = "";
result = result + genNameValueEntry("protocol", "icmp");
if (icmpType.equals("-1")) {
result = result + genNameValueEntry("icmp-type", "0-255");
} else {
result = result + genNameValueEntry("icmp-type", icmpType);
}
if (icmpCode.equals("-1")) {
result = result + genNameValueEntry("icmp-code", "0-255");
} else {
result = result + genNameValueEntry("icmp-code", icmpCode);
}
return result;
}
private boolean manageFirewallFilter(SrxCommand command, FirewallFilterTerm term, String filterName) throws ExecutionException {
String xml;
switch (command) {
case CHECK_IF_EXISTS:
xml = SrxXml.FIREWALL_FILTER_TERM_GETONE.getXml();
xml = setDelete(xml, false);
xml = replaceXmlValue(xml, "filter-name", filterName);
xml = replaceXmlValue(xml, "term-name", term.getName());
return sendRequestAndCheckResponse(command, xml, "name", term.getName());
case ADD:
if (manageFirewallFilter(SrxCommand.CHECK_IF_EXISTS, term, filterName)) {
return true;
}
xml = SrxXml.FIREWALL_FILTER_TERM_ADD.getXml();
xml = replaceXmlValue(xml, "filter-name", filterName);
xml = replaceXmlValue(xml, "term-name", term.getName());
xml = replaceXmlValue(xml, "source-address-entries", genMultipleEntries("source-address", term.getSourceCidrs()));
xml = replaceXmlValue(xml, "dest-ip-address", term.getDestIp());
String protocol = term.getProtocol();
if (protocol.equals("tcp") || protocol.equals("udp")) {
xml = replaceXmlValue(xml, "protocol-options", genPortRangeEntry(protocol, term.getPortRange()));
} else if (protocol.equals("icmp")) {
xml = replaceXmlValue(xml, "protocol-options", genIcmpEntries(term.getIcmpType(), term.getIcmpCode()));
} else {
assert protocol.equals("any");
xml = replaceXmlValue(xml, "protocol-options", "");
}
xml = replaceXmlValue(xml, "count-name", term.getCountName());
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to add firewall filter: " + term.getName());
} else {
return true;
}
case DELETE:
if (!manageFirewallFilter(SrxCommand.CHECK_IF_EXISTS, term, filterName)) {
return true;
}
xml = SrxXml.FIREWALL_FILTER_TERM_GETONE.getXml();
xml = setDelete(xml, true);
xml = replaceXmlValue(xml, "filter-name", filterName);
xml = replaceXmlValue(xml, "term-name", term.getName());
if (!sendRequestAndCheckResponse(command, xml)) {
throw new ExecutionException("Failed to delete firewall filter: " + term.getName());
} else {
return true;
}
default:
s_logger.debug("Unrecognized command.");
return false;
}
}
/*
* Usage
*/
private ExternalNetworkResourceUsageAnswer getUsageAnswer(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
try {
String socOpenException = "Failed to open a connection for Usage data.";
String socCloseException = "Unable to close connection for Usage data.";
if (!openUsageSocket()) {
throw new ExecutionException(socOpenException);
}
ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd);
String xml = SrxXml.FIREWALL_FILTER_BYTES_GETALL.getXml();
String rawUsageData = sendUsageRequest(xml);
Document doc = getDocument(rawUsageData);
NodeList counters = doc.getElementsByTagName("counter");
for (int i = 0; i < counters.getLength(); i++) {
Node n = counters.item(i);
if (n.getNodeName().equals("counter")) {
NodeList counterInfoList = n.getChildNodes();
String counterName = null;
long byteCount = 0;
for (int j = 0; j < counterInfoList.getLength(); j++) {
Node counterInfo = counterInfoList.item(j);
if (counterInfo.getNodeName().equals("counter-name")) {
counterName = counterInfo.getFirstChild().getNodeValue();
} else if (counterInfo.getNodeName().equals("byte-count")) {
try {
byteCount = Long.parseLong(counterInfo.getFirstChild().getNodeValue());
} catch (Exception e) {
s_logger.debug(e);
byteCount = 0;
}
}
}
if (byteCount >= 0) {
updateUsageAnswer(answer, counterName, byteCount);
}
}
}
if (!closeUsageSocket()) {
throw new ExecutionException(socCloseException);
}
return answer;
} catch (Exception e) {
closeUsageSocket();
throw new ExecutionException(e.getMessage());
}
}
private void updateBytesMap(Map<String, long[]> bytesMap, UsageFilter filter, String usageAnswerKey, long additionalBytes) {
long[] bytesSentAndReceived = bytesMap.get(usageAnswerKey);
if (bytesSentAndReceived == null) {
bytesSentAndReceived = new long[] {0, 0};
}
int index = 0;
if (filter.equals(_usageFilterVlanOutput) || filter.equals(_usageFilterIPInput)) {
index = 1;
}
bytesSentAndReceived[index] += additionalBytes;
bytesMap.put(usageAnswerKey, bytesSentAndReceived);
}
private String getIpAddress(String counterName) {
String[] counterNameArray = counterName.split("-");
if (counterNameArray.length < 4) {
return null;
} else {
return counterNameArray[0] + "." + counterNameArray[1] + "." + counterNameArray[2] + "." + counterNameArray[3];
}
}
private String getGuestVlanTag(String counterName) {
String[] counterNameArray = counterName.split("-");
if (counterNameArray.length != 3) {
return null;
} else {
return counterNameArray[2];
}
}
private UsageFilter getUsageFilter(String counterName) {
if (counterName.contains(_usageFilterVlanInput.getCounterIdentifier())) {
return _usageFilterVlanInput;
} else if (counterName.contains(_usageFilterVlanOutput.getCounterIdentifier())) {
return _usageFilterVlanOutput;
} else if (counterName.contains(_usageFilterIPInput.getCounterIdentifier())) {
return _usageFilterIPInput;
} else if (counterName.contains(_usageFilterIPOutput.getCounterIdentifier())) {
return _usageFilterIPOutput;
}
return null;
}
private String getUsageAnswerKey(UsageFilter filter, String counterName) {
if (filter.equals(_usageFilterVlanInput) || filter.equals(_usageFilterVlanOutput)) {
return getGuestVlanTag(counterName);
} else if (filter.equals(_usageFilterIPInput) || filter.equals(_usageFilterIPOutput)) {
return getIpAddress(counterName);
} else {
return null;
}
}
private Map<String, long[]> getBytesMap(ExternalNetworkResourceUsageAnswer answer, UsageFilter filter, String usageAnswerKey) {
if (filter.equals(_usageFilterVlanInput) || filter.equals(_usageFilterVlanOutput)) {
return answer.guestVlanBytes;
} else if (filter.equals(_usageFilterIPInput) || filter.equals(_usageFilterIPOutput)) {
return answer.ipBytes;
} else {
return null;
}
}
private void updateUsageAnswer(ExternalNetworkResourceUsageAnswer answer, String counterName, long byteCount) {
if (counterName == null || byteCount <= 0) {
return;
}
UsageFilter filter = getUsageFilter(counterName);
if (filter == null) {
s_logger.debug("Failed to parse counter name in usage answer: " + counterName);
return;
}
String usageAnswerKey = getUsageAnswerKey(filter, counterName);
Map<String, long[]> bytesMap = getBytesMap(answer, filter, usageAnswerKey);
updateBytesMap(bytesMap, filter, usageAnswerKey, byteCount);
}
/*
* XML API commands
*/
private String sendRequestPrim(BufferedWriter sendStream, BufferedReader recvStream, String xmlRequest) throws ExecutionException {
if (!xmlRequest.contains("request-login")) {
s_logger.debug("Sending request: " + xmlRequest);
} else {
s_logger.debug("Sending login request");
}
boolean timedOut = false;
StringBuffer xmlResponseBuffer = new StringBuffer("");
try {
sendStream.write(xmlRequest);
sendStream.flush();
String line = "";
while ((line = recvStream.readLine()) != null) {
xmlResponseBuffer.append(line);
if (line.contains("</rpc-reply>")) {
break;
}
}
} catch (SocketTimeoutException e) {
s_logger.debug(e);
timedOut = true;
} catch (IOException e) {
s_logger.debug(e);
return null;
}
String xmlResponse = xmlResponseBuffer.toString();
String errorMsg = null;
if (timedOut) {
errorMsg = "Timed out on XML request: " + xmlRequest;
} else if (xmlResponse.isEmpty()) {
errorMsg = "Received an empty XML response.";
} else if (xmlResponse.contains("Unexpected XML tag type")) {
errorMsg = "Sent a command without being logged in.";
} else if (!xmlResponse.contains("</rpc-reply>")) {
errorMsg = "Didn't find the rpc-reply tag in the XML response.";
}
if (errorMsg == null) {
return xmlResponse;
} else {
s_logger.error(errorMsg);
throw new ExecutionException(errorMsg);
}
}
private String sendRequest(String xmlRequest) throws ExecutionException {
return sendRequestPrim(_toSrx, _fromSrx, xmlRequest);
}
private String sendUsageRequest(String xmlRequest) throws ExecutionException {
return sendRequestPrim(_UsagetoSrx, _UsagefromSrx, xmlRequest);
}
private boolean checkResponse(String xmlResponse, boolean errorKeyAndValue, String key, String value) {
if (xmlResponse == null) {
s_logger.error("Failed to communicate with SRX!");
return false;
}
if (!xmlResponse.contains("authentication-response")) {
s_logger.debug("Checking response: " + xmlResponse);
} else {
s_logger.debug("Checking login response");
}
String textToSearchFor = key;
if (value != null) {
textToSearchFor = "<" + key + ">" + value + "</" + key + ">";
}
if ((errorKeyAndValue && !xmlResponse.contains(textToSearchFor)) || (!errorKeyAndValue && xmlResponse.contains(textToSearchFor))) {
return true;
}
String responseMessage = extractXml(xmlResponse, "message");
if (responseMessage != null) {
s_logger.error("Request failed due to: " + responseMessage);
} else {
if (errorKeyAndValue) {
s_logger.error("Found error (" + textToSearchFor + ") in response.");
} else {
s_logger.debug("Didn't find " + textToSearchFor + " in response.");
}
}
return false;
}
private boolean sendRequestAndCheckResponse(SrxCommand command, String xmlRequest, String... keyAndValue) throws ExecutionException {
boolean errorKeyAndValue = false;
String key;
String value;
switch (command) {
case LOGIN:
key = "status";
value = "success";
break;
case OPEN_CONFIGURATION:
case CLOSE_CONFIGURATION:
errorKeyAndValue = true;
key = "error";
value = null;
break;
case COMMIT:
key = "commit-success";
value = null;
break;
case CHECK_IF_EXISTS:
case CHECK_IF_IN_USE:
case CHECK_PRIVATE_IF_EXISTS:
assert (keyAndValue != null && keyAndValue.length == 2) : "If the SrxCommand is " + command + ", both a key and value must be specified.";
key = keyAndValue[0];
value = keyAndValue[1];
break;
default:
key = "load-success";
value = null;
break;
}
String xmlResponse = sendRequest(xmlRequest);
return checkResponse(xmlResponse, errorKeyAndValue, key, value);
}
private boolean sendUsageRequestAndCheckResponse(SrxCommand command, String xmlRequest, String... keyAndValue) throws ExecutionException {
boolean errorKeyAndValue = false;
String key;
String value;
switch (command) {
case LOGIN:
key = "status";
value = "success";
break;
case OPEN_CONFIGURATION:
case CLOSE_CONFIGURATION:
errorKeyAndValue = true;
key = "error";
value = null;
break;
case COMMIT:
key = "commit-success";
value = null;
break;
case CHECK_IF_EXISTS:
case CHECK_IF_IN_USE:
assert (keyAndValue != null && keyAndValue.length == 2) : "If the SrxCommand is " + command + ", both a key and value must be specified.";
key = keyAndValue[0];
value = keyAndValue[1];
break;
default:
key = "load-success";
value = null;
break;
}
String xmlResponse = sendUsageRequest(xmlRequest);
return checkResponse(xmlResponse, errorKeyAndValue, key, value);
}
/*
* XML utils
*/
private String replaceXmlTag(String xml, String oldTag, String newTag) {
return xml.replaceAll(oldTag, newTag);
}
private String replaceXmlValue(String xml, String marker, String value) {
marker = "\\s*%" + marker + "%\\s*";
if (value == null) {
value = "";
}
return xml.replaceAll(marker, value);
}
private String extractXml(String xml, String marker) {
String startMarker = "<" + marker + ">";
String endMarker = "</" + marker + ">";
if (xml.contains(startMarker) && xml.contains(endMarker)) {
return xml.substring(xml.indexOf(startMarker) + startMarker.length(), xml.indexOf(endMarker));
} else {
return null;
}
}
private String setDelete(String xml, boolean delete) {
if (delete) {
String deleteMarker = " delete=\"delete\"";
xml = replaceXmlTag(xml, "get-configuration", "load-configuration");
xml = replaceXmlValue(xml, "delete", deleteMarker);
} else {
xml = replaceXmlTag(xml, "load-configuration", "get-configuration");
xml = replaceXmlValue(xml, "delete", "");
}
return xml;
}
/*
* Misc
*/
private Long getVlanTag(String vlan) throws ExecutionException {
Long publicVlanTag = null;
if (!vlan.contains("untagged")) {
try {
// make sure this vlan is numeric
publicVlanTag = Long.parseLong(BroadcastDomainType.getValue(vlan));
} catch (Exception e) {
throw new ExecutionException("Unable to parse VLAN tag: " + vlan);
}
}
return publicVlanTag;
}
private String genObjectName(String... args) {
String objectName = "";
for (int i = 0; i < args.length; i++) {
objectName += args[i];
if (i != args.length - 1) {
objectName += _objectNameWordSep;
}
}
return objectName;
}
private String genIpIdentifier(String ip) {
return ip.replace('.', '-').replace('/', '-');
}
private Protocol getProtocol(String protocolName) throws ExecutionException {
protocolName = protocolName.toLowerCase();
try {
return Protocol.valueOf(protocolName);
} catch (Exception e) {
throw new ExecutionException("Invalid protocol: " + protocolName);
}
}
private Document getDocument(String xml) throws ExecutionException {
StringReader srcNatRuleReader = new StringReader(xml);
InputSource srcNatRuleSource = new InputSource(srcNatRuleReader);
Document doc = null;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(srcNatRuleSource);
} catch (Exception e) {
s_logger.error(e);
throw new ExecutionException(e.getMessage());
}
if (doc == null) {
throw new ExecutionException("Failed to parse xml " + xml);
} else {
return doc;
}
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
}