You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ya...@apache.org on 2013/11/06 19:08:40 UTC
[1/5] Squashed commit of the Palo Alto Networks firewall integration
plugin.
Updated Branches:
refs/heads/master 40a783932 -> 8f8ad3f38
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 1579d16..fa22811 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -4944,6 +4944,288 @@
}
},
+ // Palo Alto provider detailView
+ pa: {
+ type: 'detailView',
+ id: 'paProvider',
+ label: 'label.PA',
+ viewAll: {
+ label: 'label.devices',
+ path: '_zone.paDevices'
+ },
+ tabs: {
+ details: {
+ title: 'label.details',
+ fields: [{
+ name: {
+ label: 'label.name'
+ }
+ }, {
+ state: {
+ label: 'label.state'
+ }
+ }],
+ dataProvider: function (args) {
+ refreshNspData("PaloAlto");
+ var providerObj;
+ $(nspHardcodingArray).each(function () {
+ if (this.id == "pa") {
+ providerObj = this;
+ return false; //break each loop
+ }
+ });
+ args.response.success({
+ data: providerObj,
+ actionFilter: networkProviderActionFilter('pa')
+ });
+ }
+ }
+ },
+ actions: {
+ add: {
+ label: 'label.add.PA.device',
+ createForm: {
+ title: 'label.add.PA.device',
+ fields: {
+ ip: {
+ label: 'label.ip.address',
+ docID: 'helpPaloAltoIPAddress'
+ },
+ username: {
+ label: 'label.username',
+ docID: 'helpPaloAltoUsername'
+ },
+ password: {
+ label: 'label.password',
+ isPassword: true,
+ docID: 'helpPaloAltoPassword'
+ },
+ networkdevicetype: {
+ label: 'label.type',
+ docID: 'helpPaloAltoType',
+ select: function (args) {
+ var items = [];
+ items.push({
+ id: "PaloAltoFirewall",
+ description: "Palo Alto Firewall"
+ });
+ args.response.success({
+ data: items
+ });
+ }
+ },
+ publicinterface: {
+ label: 'label.public.interface',
+ docID: 'helpPaloAltoPublicInterface'
+ },
+ privateinterface: {
+ label: 'label.private.interface',
+ docID: 'helpPaloAltoPrivateInterface'
+ },
+ //usageinterface: {
+ // label: 'Usage interface',
+ // docID: 'helpPaloAltoUsageInterface'
+ //},
+ numretries: {
+ label: 'label.numretries',
+ defaultValue: '2',
+ docID: 'helpPaloAltoRetries'
+ },
+ timeout: {
+ label: 'label.timeout',
+ defaultValue: '300',
+ docID: 'helpPaloAltoTimeout'
+ },
+ // inline: {
+ // label: 'Mode',
+ // docID: 'helpPaloAltoMode',
+ // select: function(args) {
+ // var items = [];
+ // items.push({id: "false", description: "side by side"});
+ // items.push({id: "true", description: "inline"});
+ // args.response.success({data: items});
+ // }
+ // },
+ publicnetwork: {
+ label: 'label.public.network',
+ defaultValue: 'untrust',
+ docID: 'helpPaloAltoPublicNetwork'
+ },
+ privatenetwork: {
+ label: 'label.private.network',
+ defaultValue: 'trust',
+ docID: 'helpPaloAltoPrivateNetwork'
+ },
+ pavr: {
+ label: 'label.virtual.router',
+ docID: 'helpPaloAltoVirtualRouter'
+ },
+ patp: {
+ label: 'label.PA.threat.profile',
+ docID: 'helpPaloAltoThreatProfile'
+ },
+ palp: {
+ label: 'label.PA.log.profile',
+ docID: 'helpPaloAltoLogProfile'
+ },
+ capacity: {
+ label: 'label.capacity',
+ validation: {
+ required: false,
+ number: true
+ },
+ docID: 'helpPaloAltoCapacity'
+ },
+ dedicated: {
+ label: 'label.dedicated',
+ isBoolean: true,
+ isChecked: false,
+ docID: 'helpPaloAltoDedicated'
+ }
+ }
+ },
+ action: function (args) {
+ if (nspMap["pa"] == null) {
+ $.ajax({
+ url: createURL("addNetworkServiceProvider&name=PaloAlto&physicalnetworkid=" + selectedPhysicalNetworkObj.id),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var jobId = json.addnetworkserviceproviderresponse.jobid;
+ var addPaloAltoProviderIntervalID = setInterval(function () {
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId=" + jobId),
+ dataType: "json",
+ success: function (json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ } else {
+ clearInterval(addPaloAltoProviderIntervalID);
+ if (result.jobstatus == 1) {
+ nspMap["pa"] = json.queryasyncjobresultresponse.jobresult.networkserviceprovider;
+ addExternalFirewall(args, selectedPhysicalNetworkObj, "addPaloAltoFirewall", "addpaloaltofirewallresponse", "pafirewall");
+ } else if (result.jobstatus == 2) {
+ alert("addNetworkServiceProvider&name=Palo Alto failed. Error: " + _s(result.jobresult.errortext));
+ }
+ }
+ },
+ error: function (XMLHttpResponse) {
+ var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+ alert("addNetworkServiceProvider&name=Palo Alto failed. Error: " + errorMsg);
+ }
+ });
+ }, 3000);
+ }
+ });
+ } else {
+ addExternalFirewall(args, selectedPhysicalNetworkObj, "addPaloAltoFirewall", "addpaloaltofirewallresponse", "pafirewall");
+ }
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.add.PA.device';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+ enable: {
+ label: 'label.enable.provider',
+ action: function (args) {
+ $.ajax({
+ url: createURL("updateNetworkServiceProvider&id=" + nspMap["pa"].id + "&state=Enabled"),
+ dataType: "json",
+ success: function (json) {
+ var jid = json.updatenetworkserviceproviderresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getUpdatedItem: function (json) {
+ $(window).trigger('cloudStack.fullRefresh');
+ }
+ }
+ });
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'message.confirm.enable.provider';
+ },
+ notification: function () {
+ return 'label.enable.provider';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+ disable: {
+ label: 'label.disable.provider',
+ action: function (args) {
+ $.ajax({
+ url: createURL("updateNetworkServiceProvider&id=" + nspMap["pa"].id + "&state=Disabled"),
+ dataType: "json",
+ success: function (json) {
+ var jid = json.updatenetworkserviceproviderresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid,
+ getUpdatedItem: function (json) {
+ $(window).trigger('cloudStack.fullRefresh');
+ }
+ }
+ });
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'message.confirm.disable.provider';
+ },
+ notification: function () {
+ return 'label.disable.provider';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ },
+ destroy: {
+ label: 'label.shutdown.provider',
+ action: function (args) {
+ $.ajax({
+ url: createURL("deleteNetworkServiceProvider&id=" + nspMap["pa"].id),
+ dataType: "json",
+ success: function (json) {
+ var jid = json.deletenetworkserviceproviderresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid
+ }
+ });
+
+ $(window).trigger('cloudStack.fullRefresh');
+ }
+ });
+ },
+ messages: {
+ confirm: function (args) {
+ return 'message.confirm.shutdown.provider';
+ },
+ notification: function (args) {
+ return 'label.shutdown.provider';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ }
+ }
+ },
+
// Security groups detail view
securityGroups: {
id: 'securityGroup-providers',
@@ -9156,6 +9438,250 @@
}
}
},
+
+ //Palo Alto devices listView
+ paDevices: {
+ id: 'paDevices',
+ title: 'label.devices',
+ listView: {
+ id: 'paDevices',
+ fields: {
+ ipaddress: {
+ label: 'label.ip.address'
+ },
+ fwdevicestate: {
+ label: 'label.status'
+ },
+ fwdevicename: {
+ label: 'label.type'
+ }
+ },
+ actions: {
+ add: {
+ label: 'label.add.PA.device',
+ createForm: {
+ title: 'label.add.PA.device',
+ fields: {
+ ip: {
+ label: 'label.ip.address'
+ },
+ username: {
+ label: 'label.username'
+ },
+ password: {
+ label: 'label.password',
+ isPassword: true
+ },
+ networkdevicetype: {
+ label: 'label.type',
+ select: function (args) {
+ var items = [];
+ items.push({
+ id: "PaloAltoFirewall",
+ description: "Palo Alto Firewall"
+ });
+ args.response.success({
+ data: items
+ });
+ }
+ },
+ publicinterface: {
+ label: 'label.public.interface'
+ },
+ privateinterface: {
+ label: 'label.private.interface'
+ },
+ //usageinterface: {
+ // label: 'label.usage.interface'
+ //},
+ numretries: {
+ label: 'label.numretries',
+ defaultValue: '2'
+ },
+ timeout: {
+ label: 'label.timeout',
+ defaultValue: '300'
+ },
+ // inline: {
+ // label: 'Mode',
+ // select: function(args) {
+ // var items = [];
+ // items.push({id: "false", description: "side by side"});
+ // items.push({id: "true", description: "inline"});
+ // args.response.success({data: items});
+ // }
+ // },
+ publicnetwork: {
+ label: 'label.public.network',
+ defaultValue: 'untrust'
+ },
+ privatenetwork: {
+ label: 'label.private.network',
+ defaultValue: 'trust'
+ },
+ pavr: {
+ label: 'label.virtual.router'
+ },
+ patp: {
+ label: 'label.PA.threat.profile'
+ },
+ palp: {
+ label: 'label.PA.log.profile'
+ },
+ capacity: {
+ label: 'label.capacity',
+ validation: {
+ required: false,
+ number: true
+ }
+ },
+ dedicated: {
+ label: 'label.dedicated',
+ isBoolean: true,
+ isChecked: false
+ }
+ }
+ },
+ action: function (args) {
+ if (nspMap["pa"] == null) {
+ $.ajax({
+ url: createURL("addNetworkServiceProvider&name=PaloAlto&physicalnetworkid=" + selectedPhysicalNetworkObj.id),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var jobId = json.addnetworkserviceproviderresponse.jobid;
+ var addPaloAltoProviderIntervalID = setInterval(function () {
+ $.ajax({
+ url: createURL("queryAsyncJobResult&jobId=" + jobId),
+ dataType: "json",
+ success: function (json) {
+ var result = json.queryasyncjobresultresponse;
+ if (result.jobstatus == 0) {
+ return; //Job has not completed
+ } else {
+ clearInterval(addPaloAltoProviderIntervalID);
+ if (result.jobstatus == 1) {
+ nspMap["pa"] = json.queryasyncjobresultresponse.jobresult.networkserviceprovider;
+ addExternalFirewall(args, selectedPhysicalNetworkObj, "addPaloAltoFirewall", "addpaloaltofirewallresponse", "pafirewall");
+ } else if (result.jobstatus == 2) {
+ alert("addNetworkServiceProvider&name=Palo Alto failed. Error: " + _s(result.jobresult.errortext));
+ }
+ }
+ },
+ error: function (XMLHttpResponse) {
+ var errorMsg = parseXMLHttpResponse(XMLHttpResponse);
+ alert("addNetworkServiceProvider&name=Palo Alto failed. Error: " + errorMsg);
+ }
+ });
+ }, 3000);
+ }
+ });
+ } else {
+ addExternalFirewall(args, selectedPhysicalNetworkObj, "addPaloAltoFirewall", "addpaloaltofirewallresponse", "pafirewall");
+ }
+ },
+ messages: {
+ notification: function (args) {
+ return 'label.add.PA.device';
+ }
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ }
+ },
+ dataProvider: function (args) {
+ $.ajax({
+ url: createURL("listPaloAltoFirewalls&physicalnetworkid=" + selectedPhysicalNetworkObj.id),
+ data: {
+ page: args.page,
+ pageSize: pageSize
+ },
+ dataType: "json",
+ async: false,
+ success: function (json) {
+ var items = json.listpaloaltofirewallresponse.paloaltofirewall;
+ args.response.success({
+ data: items
+ });
+ }
+ });
+ },
+ detailView: {
+ name: 'Palo Alto details',
+ actions: {
+ 'remove': {
+ label: 'label.delete.PA',
+ messages: {
+ confirm: function (args) {
+ return 'message.confirm.delete.PA';
+ },
+ notification: function (args) {
+ return 'label.delete.PA';
+ }
+ },
+ action: function (args) {
+ $.ajax({
+ url: createURL("deletePaloAltoFirewall&fwdeviceid=" + args.context.paDevices[0].fwdeviceid),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var jid = json.deletepaloaltofirewallresponse.jobid;
+ args.response.success({
+ _custom: {
+ jobId: jid
+ }
+ });
+ }
+ });
+ },
+ notification: {
+ poll: pollAsyncJobResult
+ }
+ }
+ },
+ tabs: {
+ details: {
+ title: 'label.details',
+ fields: [{
+ fwdeviceid: {
+ label: 'label.id'
+ },
+ ipaddress: {
+ label: 'label.ip.address'
+ },
+ fwdevicestate: {
+ label: 'label.status'
+ },
+ fwdevicename: {
+ label: 'label.type'
+ },
+ fwdevicecapacity: {
+ label: 'label.capacity'
+ },
+ timeout: {
+ label: 'label.timeout'
+ }
+ }],
+ dataProvider: function (args) {
+ $.ajax({
+ url: createURL("listPaloAltoFirewalls&fwdeviceid=" + args.context.paDevices[0].fwdeviceid),
+ dataType: "json",
+ async: true,
+ success: function (json) {
+ var item = json.listpaloaltofirewallresponse.paloaltofirewall[0];
+ args.response.success({
+ data: item
+ });
+ }
+ });
+ }
+ }
+ }
+ }
+ }
+ },
+
// FIXME convert to nicira detailview
// NiciraNvp devices listView
niciraNvpDevices: {
@@ -15763,6 +16289,44 @@
}
url.push("fwdevicededicated=" + dedicated.toString());
+ // START - Palo Alto Specific Fields
+ var externalVirtualRouter = args.data.pavr;
+ if(externalVirtualRouter != null && externalVirtualRouter.length > 0) {
+ if(isQuestionMarkAdded == false) {
+ url.push("?");
+ isQuestionMarkAdded = true;
+ }
+ else {
+ url.push("&");
+ }
+ url.push("pavr=" + encodeURIComponent(externalVirtualRouter));
+ }
+
+ var externalThreatProfile = args.data.patp;
+ if(externalThreatProfile != null && externalThreatProfile.length > 0) {
+ if(isQuestionMarkAdded == false) {
+ url.push("?");
+ isQuestionMarkAdded = true;
+ }
+ else {
+ url.push("&");
+ }
+ url.push("patp=" + encodeURIComponent(externalThreatProfile));
+ }
+
+ var externalLogProfile = args.data.palp;
+ if(externalLogProfile != null && externalLogProfile.length > 0) {
+ if(isQuestionMarkAdded == false) {
+ url.push("?");
+ isQuestionMarkAdded = true;
+ }
+ else {
+ url.push("&");
+ }
+ url.push("palp=" + encodeURIComponent(externalLogProfile));
+ }
+ // END - Palo Alto Specific Fields
+
array1.push("&url=" + todb(url.join("")));
//construct URL ends here
@@ -16495,6 +17059,9 @@
case "JuniperSRX":
nspMap["srx"] = items[i];
break;
+ case "PaloAlto":
+ nspMap["pa"] = items[i];
+ break;
case "SecurityGroupProvider":
nspMap["securityGroups"] = items[i];
break;
@@ -16576,6 +17143,11 @@
name: 'SRX',
state: nspMap.srx ? nspMap.srx.state : 'Disabled'
});
+ nspHardcodingArray.push({
+ id: 'pa',
+ name: 'Palo Alto',
+ state: nspMap.pa ? nspMap.pa.state : 'Disabled'
+ });
}
};
[2/5] Squashed commit of the Palo Alto Networks firewall integration
plugin.
Posted by ya...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/network/utils/HttpClientWrapper.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/utils/HttpClientWrapper.java b/plugins/network-elements/palo-alto/src/com/cloud/network/utils/HttpClientWrapper.java
new file mode 100644
index 0000000..7e40570
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/network/utils/HttpClientWrapper.java
@@ -0,0 +1,69 @@
+package com.cloud.network.utils;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import java.io.*;
+
+public class HttpClientWrapper {
+
+ public static HttpClient wrapClient(HttpClient base) {
+ try {
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ X509TrustManager tm = new X509TrustManager() {
+
+ public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ };
+ X509HostnameVerifier verifier = new X509HostnameVerifier() {
+
+ @Override
+ public void verify(String string, SSLSocket ssls) throws IOException {
+ }
+
+ @Override
+ public void verify(String string, X509Certificate xc) throws SSLException {
+ }
+
+ @Override
+ public void verify(String string, String[] strings, String[] strings1) throws SSLException {
+ }
+
+ @Override
+ public boolean verify(String string, SSLSession ssls) {
+ return true;
+ }
+ };
+ ctx.init(null, new TrustManager[]{tm}, null);
+ SSLSocketFactory ssf = new SSLSocketFactory(ctx);
+ ssf.setHostnameVerifier(verifier);
+ ClientConnectionManager ccm = base.getConnectionManager();
+ SchemeRegistry sr = ccm.getSchemeRegistry();
+ sr.register(new Scheme("https", ssf, 443));
+ return new DefaultHttpClient(ccm, base.getParams());
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java b/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java
new file mode 100755
index 0000000..9a9eb6e
--- /dev/null
+++ b/plugins/network-elements/palo-alto/test/com/cloud/network/resource/MockablePaloAltoResource.java
@@ -0,0 +1,460 @@
+// 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.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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 javax.naming.ConfigurationException;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+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.SetFirewallRulesCommand;
+import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+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.rules.FirewallRule;
+import com.cloud.network.rules.FirewallRule.TrafficType;
+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;
+
+// http client handling
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.protocol.HTTP;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.net.URLDecoder;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import com.cloud.network.utils.HttpClientWrapper;
+
+// for prettyFormat()
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import java.io.StringWriter;
+
+
+public class MockablePaloAltoResource extends PaloAltoResource {
+ private HashMap<String, String> context;
+ public void setMockContext(HashMap<String, String> context) {
+ this.context = context;
+ }
+
+ /* Fake the calls to the Palo Alto API */
+ protected String request(PaloAltoMethod method, Map<String, String> params) throws ExecutionException {
+ if (method != PaloAltoMethod.GET && method != PaloAltoMethod.POST) {
+ throw new ExecutionException("Invalid http method used to access the Palo Alto API.");
+ }
+
+ String response = "";
+
+ // 'keygen' request
+ if (params.containsKey("type") && params.get("type").equals("keygen")) {
+ response = "<response status = 'success'><result><key>LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09</key></result></response>";
+ }
+
+ // 'config' requests
+ if (params.containsKey("type") && params.get("type").equals("config") && params.containsKey("action")) {
+ // action = 'get'
+ if (params.get("action").equals("get")) {
+ // get interface for type
+ // | public_using_ethernet
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/1']")) {
+ if (context.containsKey("public_using_ethernet") && context.get("public_using_ethernet").equals("true")) {
+ context.put("public_interface_type", "ethernet");
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"ethernet1/1\" admin=\"admin\" time=\"2013/06/18 13:33:56\"><layer3 admin=\"admin\" time=\"2013/06/18 13:33:56\"><ipv6><neighbor-discovery><router-advertisement><enable>no</enable><min-interval>200</min-interval><max-interval>600</max-interval><hop-limit>64</hop-limit><reachable-time>unspecified</reachable-time><retransmission-timer>unspecified</retransmission-timer><lifetime>1800</lifetime><managed-flag>no</managed-flag><other-flag>no</other-flag><enable-consistency-check>no</enable-consistency-check><link-mtu>unspecified</link-mtu></router-advertisement><enable-dad>no</enable-dad><reachable-time>30</reachable-time><ns-interval>1</ns-interval><dad-attempts>1</dad-attempts></neighbor-discovery><enabled>no</enabled><interface-id>EUI-64</interface-id></ipv6><untagged-sub-interface>no</untagged-sub-interface><units admin=\"admin\" time=\"2013/06/18 13:33:56\">
<entry name=\"ethernet1/1.9999\" admin=\"admin\" time=\"2013/06/18 13:33:56\"><ipv6><neighbor-discovery><router-advertisement><enable>no</enable><min-interval>200</min-interval><max-interval>600</max-interval><hop-limit>64</hop-limit><reachable-time>unspecified</reachable-time><retransmission-timer>unspecified</retransmission-timer><lifetime>1800</lifetime><managed-flag>no</managed-flag><other-flag>no</other-flag><enable-consistency-check>no</enable-consistency-check><link-mtu>unspecified</link-mtu></router-advertisement><enable-dad>no</enable-dad><reachable-time>30</reachable-time><ns-interval>1</ns-interval><dad-attempts>1</dad-attempts></neighbor-discovery><enabled>no</enabled><interface-id>EUI-64</interface-id></ipv6><ip admin=\"admin\" time=\"2013/06/18 13:33:56\"><entry name=\"192.168.80.254/24\"/></ip><adjust-tcp-mss>no</adjust-tcp-mss><tag>3033</tag></entry></units></layer3><link-speed>auto</link-speed><link-duplex>auto</link-duplex><link-state>auto</link-state></entry></res
ult></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ } // | private_using_ethernet
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/2']")) {
+ if (context.containsKey("private_using_ethernet") && context.get("private_using_ethernet").equals("true")) {
+ context.put("private_interface_type", "ethernet");
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"ethernet1/2\" admin=\"admin\" time=\"2013/06/18 13:33:57\"><layer3 admin=\"admin\" time=\"2013/06/18 13:33:57\"><ipv6><neighbor-discovery><router-advertisement><enable>no</enable><min-interval>200</min-interval><max-interval>600</max-interval><hop-limit>64</hop-limit><reachable-time>unspecified</reachable-time><retransmission-timer>unspecified</retransmission-timer><lifetime>1800</lifetime><managed-flag>no</managed-flag><other-flag>no</other-flag><enable-consistency-check>no</enable-consistency-check><link-mtu>unspecified</link-mtu></router-advertisement><enable-dad>no</enable-dad><reachable-time>30</reachable-time><ns-interval>1</ns-interval><dad-attempts>1</dad-attempts></neighbor-discovery><enabled>no</enabled><interface-id>EUI-64</interface-id></ipv6><untagged-sub-interface>no</untagged-sub-interface><units admin=\"admin\" time=\"2013/06/18 13:33:57\"/
></layer3><link-speed>auto</link-speed><link-duplex>auto</link-duplex><link-state>auto</link-state></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get management profile | has_management_profile
+ if (params.get("xpath").equals("/config/devices/entry/network/profiles/interface-management-profile/entry[@name='Ping']")) {
+ if (context.containsKey("has_management_profile") && context.get("has_management_profile").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"Ping\"><ping>yes</ping></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get public interface IP | has_public_interface
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/1']/layer3/units/entry[@name='ethernet1/1.9999']/ip/entry[@name='192.168.80.102/32']")) {
+ if (context.containsKey("has_public_interface") && context.get("has_public_interface").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"192.168.80.102/32\" admin=\"admin\" time=\"2013/07/05 13:02:37\"/></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get private interface | has_private_interface
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/2']/layer3/units/entry[@name='ethernet1/2.3954']")) {
+ if (context.containsKey("has_private_interface") && context.get("has_private_interface").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"ethernet1/2.3954\" admin=\"admin\" time=\"2013/07/05 13:02:36\"><tag admin=\"admin\" time=\"2013/07/05 13:02:36\">3954</tag><ip><entry name=\"10.5.80.1/20\"/></ip><interface-management-profile>Ping</interface-management-profile></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get private interface ip
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/2']/layer3/units/entry[@name='ethernet1/2.3954']/ip/entry")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"10.3.96.1/20\"/></result></response>";
+ }
+
+ // get source nat | has_src_nat_rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='src_nat.3954']")) {
+ if (context.containsKey("has_src_nat_rule") && context.get("has_src_nat_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"src_nat.3954\" admin=\"admin\" time=\"2013/07/05 13:02:38\"><to admin=\"admin\" time=\"2013/07/05 13:02:38\"><member admin=\"admin\" time=\"2013/07/05 13:02:38\">untrust</member></to><from><member>trust</member></from><source><member>10.5.80.1/20</member></source><destination><member>any</member></destination><service>any</service><nat-type>ipv4</nat-type><to-interface>ethernet1/1.9999</to-interface><source-translation><dynamic-ip-and-port><interface-address><ip>192.168.80.102/32</ip><interface>ethernet1/1.9999</interface></interface-address></dynamic-ip-and-port></source-translation></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get isolation firewall rule | has_isolation_fw_rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='isolate_3954']")) {
+ if (context.containsKey("has_isolation_fw_rule") && context.get("has_isolation_fw_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"isolate_3954\" admin=\"admin\" time=\"2013/07/05 13:02:38\"><from admin=\"admin\" time=\"2013/07/05 13:02:38\"><member admin=\"admin\" time=\"2013/07/05 13:02:38\">trust</member></from><to><member>trust</member></to><source><member>10.5.80.0/20</member></source><destination><member>10.5.80.1</member></destination><application><member>any</member></application><service><member>any</member></service><action>deny</action><negate-source>no</negate-source><negate-destination>yes</negate-destination></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get service | has_service
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/service/entry[@name='cs_tcp_80']")) {
+ if (context.containsKey("has_service_tcp_80") && context.get("has_service_tcp_80").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"cs_tcp_80\"><protocol><tcp><port>80</port></tcp></protocol></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get egress firewall rule | has_egress_fw_rule | policy_0
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0']")) {
+ if (context.containsKey("has_egress_fw_rule") && context.get("has_egress_fw_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"policy_0\" admin=\"admin\" time=\"2013/07/03 12:43:30\"><from admin=\"admin\" time=\"2013/07/03 12:43:30\"><member admin=\"admin\" time=\"2013/07/03 12:43:30\">trust</member></from><to><member>untrust</member></to><source><member>10.3.96.1/20</member></source><destination><member>any</member></destination><application><member>any</member></application><service><member>cs_tcp_80</member></service><action>allow</action><negate-source>no</negate-source><negate-destination>no</negate-destination></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get ingress firewall rule | has_ingress_fw_rule | policy_8
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_8']")) {
+ if (context.containsKey("has_ingress_fw_rule") && context.get("has_ingress_fw_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"policy_8\" admin=\"admin\" time=\"2013/07/03 13:26:27\"><from admin=\"admin\" time=\"2013/07/03 13:26:27\"><member admin=\"admin\" time=\"2013/07/03 13:26:27\">untrust</member></from><to><member>trust</member></to><source><member>any</member></source><destination><member>192.168.80.103</member></destination><application><member>any</member></application><service><member>cs_tcp_80</member></service><action>allow</action><negate-source>no</negate-source><negate-destination>no</negate-destination></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get destination nat rule (port forwarding) | has_dst_nat_rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='dst_nat.192-168-80-103_9']")) {
+ if (context.containsKey("has_dst_nat_rule") && context.get("has_dst_nat_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"dst_nat.192-168-80-103_9\" admin=\"admin\" time=\"2013/07/03 13:40:50\"><to admin=\"admin\" time=\"2013/07/03 13:40:50\"><member admin=\"admin\" time=\"2013/07/03 13:40:50\">untrust</member></to><from><member>untrust</member></from><source><member>any</member></source><destination><member>192.168.80.103</member></destination><service>cs_tcp_80</service><nat-type>ipv4</nat-type><to-interface>ethernet1/1.9999</to-interface><destination-translation><translated-address>10.3.97.158</translated-address><translated-port>8080</translated-port></destination-translation></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get destination nat rules (returns all dst nat rules per ip)
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[destination/member[text()='192.168.80.103']]")) {
+ if (context.containsKey("has_dst_nat_rule") && context.get("has_dst_nat_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"dst_nat.192-168-80-103_9\" admin=\"admin\" time=\"2013/07/03 13:40:50\"><to admin=\"admin\" time=\"2013/07/03 13:40:50\"><member admin=\"admin\" time=\"2013/07/03 13:40:50\">untrust</member></to><from><member>untrust</member></from><source><member>any</member></source><destination><member>192.168.80.103</member></destination><service>cs_tcp_80</service><nat-type>ipv4</nat-type><to-interface>ethernet1/1.9999</to-interface><destination-translation><translated-address>10.3.97.158</translated-address><translated-port>8080</translated-port></destination-translation></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ // get static nat rule | has_stc_nat_rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='stc_nat.192-168-80-103_0']")) {
+ if (context.containsKey("has_stc_nat_rule") && context.get("has_stc_nat_rule").equals("true")) {
+ response = "<response status=\"success\" code=\"19\"><result total-count=\"1\" count=\"1\"><entry name=\"stc_nat.192-168-80-103_0\" admin=\"admin\" time=\"2013/07/03 14:02:23\"><to admin=\"admin\" time=\"2013/07/03 14:02:23\"><member admin=\"admin\" time=\"2013/07/03 14:02:23\">untrust</member></to><from><member>untrust</member></from><source><member>any</member></source><destination><member>192.168.80.103</member></destination><service>any</service><nat-type>ipv4</nat-type><to-interface>ethernet1/1.9999</to-interface><destination-translation><translated-address>10.3.97.158</translated-address></destination-translation></entry></result></response>";
+ } else {
+ response = "<response status=\"success\" code=\"19\"><result/></response>";
+ }
+ }
+
+ }
+
+ // action = 'set'
+ if (params.get("action").equals("set")) {
+ // set management profile
+ if (params.get("xpath").equals("/config/devices/entry/network/profiles/interface-management-profile/entry[@name='Ping']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_management_profile", "true");
+ }
+
+ // add private interface
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/2']/layer3/units/entry[@name='ethernet1/2.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_private_interface", "true");
+ }
+
+ // add public ip to public interface
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/1']/layer3/units/entry[@name='ethernet1/1.9999']/ip")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_public_interface", "true");
+ }
+
+ // add private interface to zone
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/zone/entry[@name='trust']/network/layer3")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // add public interface to zone
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/zone/entry[@name='untrust']/network/layer3")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // set virtual router (public | private)
+ if (params.get("xpath").equals("/config/devices/entry/network/virtual-router/entry[@name='default']/interface")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // add interface to network (public | private)
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/import/network/interface")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // add src nat rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='src_nat.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_src_nat_rule", "true");
+ }
+
+ // add isolation firewall rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='isolate_3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_isolation_fw_rule", "true");
+ }
+
+ // add egress firewall rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_egress_fw_rule", "true");
+ }
+
+ // add ingress firewall rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_8']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_ingress_fw_rule", "true");
+ }
+
+ // add destination nat rule (port forwarding)
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='dst_nat.192-168-80-103_9']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_dst_nat_rule", "true");
+ }
+
+ // add static nat rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='stc_nat.192-168-80-103_0']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_stc_nat_rule", "true");
+ }
+
+ // add tcp 80 service
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/service/entry[@name='cs_tcp_80']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.put("has_service_tcp_80", "true");
+ }
+ }
+
+ // action = 'delete'
+ if (params.get("action").equals("delete")) {
+ // remove egress firewall rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_0']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_egress_fw_rule");
+ }
+
+ // remove ingress firewall rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='policy_8']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_ingress_fw_rule");
+ }
+
+ // remove destination nat rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='dst_nat.192-168-80-103_9']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_dst_nat_rule");
+ }
+
+ // remove static nat rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='stc_nat.192-168-80-103_0']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_dst_nat_rule");
+ }
+
+ // remove public ip from interface (dst_nat | stc_nat)
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/1']/layer3/units/entry[@name='ethernet1/1.9999']/ip/entry[@name='192.168.80.103/32']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // remove isolation firewall rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='isolate_3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_isolation_fw_rule");
+ }
+
+ // remove source nat rule
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='src_nat.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_src_nat_rule");
+ }
+
+ // remove public source nat ip
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/1']/layer3/units/entry[@name='ethernet1/1.9999']/ip/entry[@name='192.168.80.102/32']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_public_interface");
+ }
+
+ // remove private interface from the zone
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/zone/entry[@name='trust']/network/layer3/member[text()='ethernet1/2.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // remove private interface from the virtual router
+ if (params.get("xpath").equals("/config/devices/entry/network/virtual-router/entry[@name='default']/interface/member[text()='ethernet1/2.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // remove private interface from network
+ if (params.get("xpath").equals("/config/devices/entry/vsys/entry[@name='vsys1']/import/network/interface/member[text()='ethernet1/2.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ }
+
+ // remove private interface
+ if (params.get("xpath").equals("/config/devices/entry/network/interface/ethernet/entry[@name='ethernet1/2']/layer3/units/entry[@name='ethernet1/2.3954']")) {
+ response = "<response status=\"success\" code=\"20\"><msg>command succeeded</msg></response>";
+ context.remove("has_private_interface");
+ }
+
+ }
+ } // end 'config'
+
+ // 'op' requests
+ if (params.containsKey("type") && params.get("type").equals("op")) {
+ // check if there are pending changes
+ if (params.get("cmd").equals("<check><pending-changes></pending-changes></check>")) {
+ if (context.containsKey("firewall_has_pending_changes") && context.get("firewall_has_pending_changes").equals("true")) {
+ response = "<response status=\"success\"><result>yes</result></response>";
+ } else {
+ response = "<response status=\"success\"><result>no</result></response>";
+ }
+ }
+
+ // add a config lock
+ if (params.get("cmd").equals("<request><config-lock><add></add></config-lock></request>")) {
+ response = "<response status=\"success\"><result>Successfully acquired lock. Other administrators will not be able to modify configuration for scope shared until lock is released</result></response>";
+ }
+
+ // check job status
+ if (params.get("cmd").equals("<show><jobs><id>1</id></jobs></show>")) {
+ if (context.containsKey("simulate_commit_failure") && context.get("simulate_commit_failure").equals("true")) {
+ response = "<response status=\"success\"><result><job><tenq>2013/07/10 11:11:49</tenq><id>1</id><user>admin</user><type>Commit</type><status>FIN</status><stoppable>no</stoppable><result>FAIL</result><tfin>11:11:54</tfin><progress>11:11:54</progress><details><line>Bad config</line><line>Commit failed</line></details><warnings></warnings></job></result></response>";
+ } else {
+ response = "<response status=\"success\"><result><job><tenq>2013/07/02 14:49:49</tenq><id>1</id><user>admin</user><type>Commit</type><status>FIN</status><stoppable>no</stoppable><result>OK</result><tfin>14:50:02</tfin><progress>14:50:02</progress><details><line>Configuration committed successfully</line></details><warnings></warnings></job></result></response>";
+ }
+ }
+
+ // load from running config
+ if (params.get("cmd").equals("<load><config><from>running-config.xml</from></config></load>")) {
+ response = "<response status=\"success\"><result><msg><line>Config loaded from running-config.xml</line></msg></result></response>";
+ }
+
+ // remove config lock
+ if (params.get("cmd").equals("<request><config-lock><remove></remove></config-lock></request>")) {
+ response = "<response status=\"success\"><result>Config lock released for scope shared</result></response>";
+ }
+ } // end 'op'
+
+ // 'commit' requests
+ if (params.containsKey("type") && params.get("type").equals("commit")) {
+ // cmd = '<commit></commit>'
+ if (params.get("cmd").equals("<commit></commit>")) {
+ response = "<response status=\"success\" code=\"19\"><result><msg><line>Commit job enqueued with jobid 1</line></msg><job>1</job></result></response>";
+ }
+ } // end 'commit'
+
+
+ // print out the details into the console
+ if (context.containsKey("enable_console_output") && context.get("enable_console_output") == "true") {
+ if (params.containsKey("xpath")) {
+ System.out.println("XPATH("+params.get("action")+"): "+params.get("xpath"));
+ }
+ if (params.containsKey("type") && params.get("type").equals("op")) {
+ System.out.println("OP CMD: "+params.get("cmd"));
+ }
+ System.out.println(response+"\n");
+ }
+
+ return response;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/test/com/cloud/network/resource/PaloAltoResourceTest.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/test/com/cloud/network/resource/PaloAltoResourceTest.java b/plugins/network-elements/palo-alto/test/com/cloud/network/resource/PaloAltoResourceTest.java
new file mode 100755
index 0000000..c270473
--- /dev/null
+++ b/plugins/network-elements/palo-alto/test/com/cloud/network/resource/PaloAltoResourceTest.java
@@ -0,0 +1,507 @@
+// 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;
+
+// test imports
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+
+// basic imports
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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 javax.naming.ConfigurationException;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+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.SetFirewallRulesCommand;
+import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+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.rules.FirewallRuleVO;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.FirewallRule.TrafficType;
+import com.cloud.network.rules.FirewallRule.Purpose;
+import com.cloud.network.rules.FirewallRule.State;
+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;
+
+// http client handling
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.protocol.HTTP;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.net.URLDecoder;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import com.cloud.network.utils.HttpClientWrapper;
+
+// for prettyFormat()
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import java.io.StringWriter;
+
+public class PaloAltoResourceTest {
+ // configuration data
+ private String _test_name = "PaloAltoTestDevice";
+ private String _test_zoneId = "TestZone";
+ private String _test_ip = "192.168.80.2";
+ private String _test_username = "admin";
+ private String _test_password = "admin";
+ private String _test_publicInterface = "ethernet1/1";
+ private String _test_privateInterface = "ethernet1/2";
+ private String _test_publicZone = "untrust";
+ private String _test_privateZone = "trust";
+ private String _test_virtualRouter = "default";
+
+ MockablePaloAltoResource _resource;
+ Map<String, Object> _resource_params;
+ HashMap<String, String> _context;
+
+ @Before
+ public void setUp() {
+ _resource = new MockablePaloAltoResource();
+ _resource_params = new HashMap<String, Object>(); // params to be passed to configure()
+ _resource_params.put("name", _test_name);
+ _resource_params.put("zoneId", _test_zoneId);
+ _resource_params.put("ip", _test_ip);
+ _resource_params.put("username", _test_username);
+ _resource_params.put("password", _test_password);
+ _resource_params.put("publicinterface", _test_publicInterface);
+ _resource_params.put("privateinterface", _test_privateInterface);
+ _resource_params.put("publicnetwork", _test_publicZone);
+ _resource_params.put("privatenetwork", _test_privateZone);
+ _resource_params.put("pavr", _test_virtualRouter);
+ _resource_params.put("guid", "aaaaa-bbbbb-ccccc");
+
+ _context = new HashMap<String, String>(); // global context
+ _context.put("name", _test_name);
+ _context.put("zone_id", _test_zoneId);
+ _context.put("ip", _test_ip);
+ _context.put("username", _test_username);
+ _context.put("password", _test_password);
+ _context.put("public_interface", _test_publicInterface);
+ _context.put("private_interface", _test_privateInterface);
+ _context.put("public_zone", _test_publicZone);
+ _context.put("private_zone", _test_privateZone);
+ _context.put("pa_vr", _test_virtualRouter);
+ // --
+ _context.put("public_using_ethernet", "true");
+ _context.put("private_using_ethernet", "true");
+ _context.put("has_management_profile", "true");
+ _context.put("enable_console_output", "false"); // CHANGE TO "true" TO ENABLE CONSOLE LOGGING OF TESTS
+ _resource.setMockContext(_context);
+ }
+
+ @Test (expected=ConfigurationException.class)
+ public void resourceConfigureFailure() throws ConfigurationException {
+ _resource.configure("PaloAltoResource", new HashMap<String, Object>());
+ }
+
+ @Test
+ public void resourceConfigureWithoutManagementProfile() throws ConfigurationException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: resourceConfigureWithoutManagementProfile");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.remove("has_management_profile");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+ }
+
+ @Test
+ public void resourceConfigureWithManagementProfile() throws ConfigurationException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: resourceConfigureWithManagementProfile");
+ System.out.println("---------------------------------------------------");
+ }
+ _resource.configure("PaloAltoResource", _resource_params);
+ }
+
+ @Test (expected=ConfigurationException.class)
+ public void simulateFirewallNotConfigurable() throws ConfigurationException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: simulateFirewallNotConfigurable");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("firewall_has_pending_changes", "true");
+ _context.remove("has_management_profile");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+ }
+
+ @Test (expected=ConfigurationException.class)
+ public void simulateFirewallCommitFailure() throws ConfigurationException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: simulateFirewallCommitFailure");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("simulate_commit_failure", "true");
+ _context.remove("has_management_profile");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+ }
+
+ @Test
+ public void testInitialize() throws ConfigurationException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: testInitialization");
+ System.out.println("---------------------------------------------------");
+ }
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ StartupCommand[] sc = _resource.initialize();
+ assertTrue(sc.length == 1);
+ assertTrue("aaaaa-bbbbb-ccccc".equals(sc[0].getGuid()));
+ assertTrue("PaloAltoTestDevice".equals(sc[0].getName()));
+ assertTrue("TestZone".equals(sc[0].getDataCenter()));
+ }
+
+ @Test // implement public & private interfaces, source nat, guest network
+ public void implementGuestNetwork() throws ConfigurationException, ExecutionException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: implementGuestNetwork");
+ System.out.println("---------------------------------------------------");
+ }
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ IpAddressTO ip = new IpAddressTO(Long.valueOf("1"), "192.168.80.102", true, false, true, "untagged", null, null, null, 100, false);
+ IpAddressTO[] ips = new IpAddressTO[1];
+ ips[0] = ip;
+ IpAssocCommand cmd = new IpAssocCommand(ips);
+ cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY, "10.3.96.1");
+ cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+ cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, "3954");
+
+ IpAssocAnswer answer = (IpAssocAnswer) _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test // remove public & private interface details, source nat, guest network
+ public void shutdownGuestNetwork() throws ConfigurationException, ExecutionException {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: shutdownGuestNetwork");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ IpAddressTO ip = new IpAddressTO(Long.valueOf("1"), "192.168.80.102", false, false, true, "untagged", null, null, null, 100, false);
+ IpAddressTO[] ips = new IpAddressTO[1];
+ ips[0] = ip;
+ IpAssocCommand cmd = new IpAssocCommand(ips);
+ cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_GATEWAY, "10.3.96.1");
+ cmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+ cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, "3954");
+
+ IpAssocAnswer answer = (IpAssocAnswer) _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void addIngressFirewallRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: addIngressFirewallRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<FirewallRuleTO> rules = new ArrayList<FirewallRuleTO>();
+ List<String> cidrList = new ArrayList<String>();
+ cidrList.add("0.0.0.0/0");
+ FirewallRuleTO active = new FirewallRuleTO(8,
+ null, "192.168.80.103", "tcp", 80, 80, false, false,
+ FirewallRule.Purpose.Firewall, cidrList, null, null);
+ rules.add(active);
+
+ SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rules);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void removeIngressFirewallRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: removeIngressFirewallRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _context.put("has_ingress_fw_rule", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<FirewallRuleTO> rules = new ArrayList<FirewallRuleTO>();
+ FirewallRuleTO revoked = new FirewallRuleTO(8,
+ null, "192.168.80.103", "tcp", 80, 80, true, false,
+ FirewallRule.Purpose.Firewall, null, null, null);
+ rules.add(revoked);
+
+ SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rules);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void addEgressFirewallRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: addEgressFirewallRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<FirewallRuleTO> rules = new ArrayList<FirewallRuleTO>();
+ List<String> cidrList = new ArrayList<String>();
+ cidrList.add("0.0.0.0/0");
+ FirewallRuleVO activeVO = new FirewallRuleVO(null, null, 80, 80, "tcp",
+ 1, 1, 1, Purpose.Firewall, cidrList, null,
+ null, null, FirewallRule.TrafficType.Egress);
+ FirewallRuleTO active = new FirewallRuleTO(activeVO, Long.toString(vlanId), null, Purpose.Firewall, FirewallRule.TrafficType.Egress);
+ rules.add(active);
+
+ SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rules);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void removeEgressFirewallRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: removeEgressFirewallRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _context.put("has_egress_fw_rule", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<FirewallRuleTO> rules = new ArrayList<FirewallRuleTO>();
+ FirewallRuleVO revokedVO = new FirewallRuleVO(null, null, 80, 80, "tcp",
+ 1, 1, 1, Purpose.Firewall, null, null, null, null, FirewallRule.TrafficType.Egress);
+ revokedVO.setState(State.Revoke);
+ FirewallRuleTO revoked = new FirewallRuleTO(revokedVO, Long.toString(vlanId), null, Purpose.Firewall, FirewallRule.TrafficType.Egress);
+ rules.add(revoked);
+
+ SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rules);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void addStaticNatRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: addStaticNatRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<StaticNatRuleTO> rules = new ArrayList<StaticNatRuleTO>();
+ StaticNatRuleTO active = new StaticNatRuleTO(0, "192.168.80.103", null,
+ null, "10.3.97.158", null, null, null, false, false);
+ rules.add(active);
+
+ SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rules, null);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void removeStaticNatRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: removeStaticNatRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _context.put("has_stc_nat_rule", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<StaticNatRuleTO> rules = new ArrayList<StaticNatRuleTO>();
+ StaticNatRuleTO revoked = new StaticNatRuleTO(0, "192.168.80.103", null,
+ null, "10.3.97.158", null, null, null, true, false);
+ rules.add(revoked);
+
+ SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rules, null);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void addPortForwardingRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: addPortForwardingRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<PortForwardingRuleTO> rules = new ArrayList<PortForwardingRuleTO>();
+ PortForwardingRuleTO active = new PortForwardingRuleTO(9, "192.168.80.103", 80,
+ 80, "10.3.97.158", 8080, 8080, "tcp", false, false);
+ rules.add(active);
+
+ SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rules);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+
+ @Test
+ public void removePortForwardingRule() throws ConfigurationException, Exception {
+ if (_context.containsKey("enable_console_output") && _context.get("enable_console_output").equals("true")) {
+ System.out.println("\nTEST: removePortForwardingRule");
+ System.out.println("---------------------------------------------------");
+ }
+ _context.put("has_public_interface", "true");
+ _context.put("has_private_interface", "true");
+ _context.put("has_src_nat_rule", "true");
+ _context.put("has_isolation_fw_rule", "true");
+ _context.put("has_service_tcp_80", "true");
+ _context.put("has_dst_nat_rule", "true");
+ _resource.setMockContext(_context);
+ _resource.configure("PaloAltoResource", _resource_params);
+
+ long vlanId = 3954;
+ List<PortForwardingRuleTO> rules = new ArrayList<PortForwardingRuleTO>();
+ PortForwardingRuleTO revoked = new PortForwardingRuleTO(9, "192.168.80.103", 80,
+ 80, "10.3.97.158", 8080, 8080, "tcp", true, false);
+ rules.add(revoked);
+
+ SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rules);
+ cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId));
+ cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "10.3.96.1/20");
+
+ Answer answer = _resource.executeRequest(cmd);
+ assertTrue(answer.getResult());
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 4f193bc..d0817a2 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -44,6 +44,7 @@
<module>network-elements/elastic-loadbalancer</module>
<module>network-elements/ovs</module>
<module>network-elements/juniper-contrail</module>
+ <module>network-elements/palo-alto</module>
<module>network-elements/nicira-nvp</module>
<module>network-elements/bigswitch-vns</module>
<module>network-elements/midonet</module>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 769d345..36ef4bd 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -2631,7 +2631,7 @@ public class ApiResponseHelper implements ResponseGenerator {
List<ProviderResponse> serviceProvidersResponses = new ArrayList<ProviderResponse>();
for (Network.Provider serviceProvider : serviceProviders) {
// return only Virtual Router/JuniperSRX/CiscoVnmc as a provider for the firewall
- if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX || serviceProvider == Provider.CiscoVnmc)) {
+ if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX || serviceProvider == Provider.CiscoVnmc || serviceProvider == Provider.PaloAlto)) {
continue;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index e3aa4fa..2e9b388 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -3792,6 +3792,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
firewallProvider = provider;
}
+ if (provider == Provider.PaloAlto) {
+ firewallProvider = Provider.PaloAlto;
+ }
+
if ((service == Service.PortForwarding || service == Service.StaticNat)
&& provider == Provider.VirtualRouter) {
firewallProvider = Provider.VirtualRouter;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/ui/dictionary.jsp
----------------------------------------------------------------------
diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp
index 85f24c6..8bd547b 100644
--- a/ui/dictionary.jsp
+++ b/ui/dictionary.jsp
@@ -322,6 +322,7 @@ dictionary = {
'label.add.new.gateway': '<fmt:message key="label.add.new.gateway" />',
'label.add.new.NetScaler': '<fmt:message key="label.add.new.NetScaler" />',
'label.add.new.SRX': '<fmt:message key="label.add.new.SRX" />',
+'label.add.new.PA': '<fmt:message key="label.add.new.PA" />',
'label.add.new.tier': '<fmt:message key="label.add.new.tier" />',
'label.add.NiciraNvp.device': '<fmt:message key="label.add.NiciraNvp.device" />',
'label.add.pod': '<fmt:message key="label.add.pod" />',
@@ -334,6 +335,7 @@ dictionary = {
'label.add.security.group': '<fmt:message key="label.add.security.group" />',
'label.add.service.offering': '<fmt:message key="label.add.service.offering" />',
'label.add.SRX.device': '<fmt:message key="label.add.SRX.device" />',
+'label.add.PA.device': '<fmt:message key="label.add.PA.device" />',
'label.add.static.nat.rule': '<fmt:message key="label.add.static.nat.rule" />',
'label.add.static.route': '<fmt:message key="label.add.static.route" />',
'label.add.system.service.offering': '<fmt:message key="label.add.system.service.offering" />',
@@ -480,6 +482,7 @@ dictionary = {
'label.delete.NiciraNvp': '<fmt:message key="label.delete.NiciraNvp" />',
'label.delete.project': '<fmt:message key="label.delete.project" />',
'label.delete.SRX': '<fmt:message key="label.delete.SRX" />',
+'label.delete.PA': '<fmt:message key="label.delete.PA" />',
'label.delete.VPN.connection': '<fmt:message key="label.delete.VPN.connection" />',
'label.delete.VPN.customer.gateway': '<fmt:message key="label.delete.VPN.customer.gateway" />',
'label.delete.VPN.gateway': '<fmt:message key="label.delete.VPN.gateway" />',
@@ -859,6 +862,8 @@ dictionary = {
'label.owned.public.ips': '<fmt:message key="label.owned.public.ips" />',
'label.owner.account': '<fmt:message key="label.owner.account" />',
'label.owner.domain': '<fmt:message key="label.owner.domain" />',
+'label.PA.log.profile': '<fmt:message key="label.PA.log.profile" />',
+'label.PA.threat.profile': '<fmt:message key="label.PA.threat.profile" />',
'label.parent.domain': '<fmt:message key="label.parent.domain" />',
'label.password.enabled': '<fmt:message key="label.password.enabled" />',
'label.password': '<fmt:message key="label.password" />',
@@ -1031,6 +1036,7 @@ dictionary = {
'label.specify.vxlan': '<fmt:message key="label.specify.vxlan" />',
'label.SR.name ': '<fmt:message key="label.SR.name " />',
'label.srx': '<fmt:message key="label.srx" />',
+'label.PA': '<fmt:message key="label.PA" />',
'label.start.IP': '<fmt:message key="label.start.IP" />',
'label.start.port': '<fmt:message key="label.start.port" />',
'label.start.reserved.system.IP': '<fmt:message key="label.start.reserved.system.IP" />',
@@ -1332,6 +1338,7 @@ dictionary = {
'message.confirm.delete.F5': '<fmt:message key="message.confirm.delete.F5" />',
'message.confirm.delete.NetScaler': '<fmt:message key="message.confirm.delete.NetScaler" />',
'message.confirm.delete.SRX': '<fmt:message key="message.confirm.delete.SRX" />',
+'message.confirm.delete.PA': '<fmt:message key="message.confirm.delete.PA" />',
'message.confirm.destroy.router': '<fmt:message key="message.confirm.destroy.router" />',
'message.confirm.disable.provider': '<fmt:message key="message.confirm.disable.provider" />',
'message.confirm.enable.provider': '<fmt:message key="message.confirm.enable.provider" />',
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/ui/scripts/docs.js
----------------------------------------------------------------------
diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js
index 3a4f8ca..7b7edf4 100755
--- a/ui/scripts/docs.js
+++ b/ui/scripts/docs.js
@@ -770,6 +770,75 @@ cloudStack.docs = {
desc: 'Number of guest networks/accounts that will share this device',
externalLink: ''
},
+ // Add Palo Alto
+ helpPaloAltoIPAddress: {
+ desc: 'The IP address of the device',
+ externalLink: ''
+ },
+ helpPaloAltoUsername: {
+ desc: 'A user ID with valid authentication credentials that provide to access the device',
+ externalLink: ''
+ },
+ helpPaloAltoPassword: {
+ desc: 'The password for the user ID provided in Username',
+ externalLink: ''
+ },
+ helpPaloAltoType: {
+ desc: 'The type of device that is being added',
+ externalLink: ''
+ },
+ helpPaloAltoPublicInterface: {
+ desc: 'Interface of device that is configured to be part of the public network. For example, ge-0/0/2',
+ externalLink: ''
+ },
+ helpPaloAltoPrivateInterface: {
+ desc: 'Interface of device that is configured to be part of the private network. For example, ge-0/0/1',
+ externalLink: ''
+ },
+ helpPaloAltoUsageInterface: {
+ desc: 'Interface used to meter traffic. If you don\'t want to use the public interface, specify a different interface name here.',
+ externalLink: ''
+ },
+ helpPaloAltoRetries: {
+ desc: 'Number of times to attempt a command on the device before considering the operation failed. Default is 2.',
+ externalLink: ''
+ },
+ helpPaloAltoTimeout: {
+ desc: 'The time to wait for a command on the Palo Alto before considering it failed. Default is 300 seconds.',
+ externalLink: ''
+ },
+ helpPaloAltoMode: {
+ desc: 'Side by side mode is supported for the Palo Alto.',
+ externalLink: ''
+ },
+ helpPaloAltoPublicNetwork: {
+ desc: 'The name of the public network on the Palo Alto. For example, trust.',
+ externalLink: ''
+ },
+ helpPaloAltoPrivateNetwork: {
+ desc: 'The name of the private network on the Palo Alto. For example, untrust.',
+ externalLink: ''
+ },
+ helpPaloAltoVirtualRouter: {
+ desc: 'The name of the virtual router on the Palo Alto.',
+ externalLink: ''
+ },
+ helpPaloAltoThreatProfile: {
+ desc: 'The threat profile name/group to associate with allow firewall policies.',
+ externalLink: ''
+ },
+ helpPaloAltoLogProfile: {
+ desc: 'The log profile name/group to associate with allow firewall policies.',
+ externalLink: ''
+ },
+ helpPaloAltoDedicated: {
+ desc: 'Check this box to dedicate the device to a single account. The value in the Capacity field will be ignored.',
+ externalLink: ''
+ },
+ helpPaloAltoCapacity: {
+ desc: 'Number of guest networks/accounts that will share this device',
+ externalLink: ''
+ },
// Add system service offering
helpSystemOfferingName: {
desc: 'Any desired name for the offering',
[4/5] Squashed commit of the Palo Alto Networks firewall integration
plugin.
Posted by ya...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java
new file mode 100644
index 0000000..3eb802e
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoExternalFirewallElement.java
@@ -0,0 +1,538 @@
+// 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.element;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.response.ExternalFirewallResponse;
+import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.commands.AddExternalFirewallCmd;
+import com.cloud.api.commands.AddPaloAltoFirewallCmd;
+import com.cloud.api.commands.ConfigurePaloAltoFirewallCmd;
+import com.cloud.api.commands.DeleteExternalFirewallCmd;
+import com.cloud.api.commands.DeletePaloAltoFirewallCmd;
+import com.cloud.api.commands.ListExternalFirewallsCmd;
+import com.cloud.api.commands.ListPaloAltoFirewallNetworksCmd;
+import com.cloud.api.commands.ListPaloAltoFirewallsCmd;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.configuration.Config;
+import com.cloud.configuration.ConfigurationManager;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InsufficientNetworkCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.ExternalFirewallDeviceManagerImpl;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PublicIpAddress;
+import com.cloud.network.dao.ExternalFirewallDeviceDao;
+import com.cloud.network.dao.ExternalFirewallDeviceVO;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkExternalFirewallDao;
+import com.cloud.network.dao.NetworkExternalFirewallVO;
+import com.cloud.network.dao.NetworkServiceMapDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.dao.ExternalFirewallDeviceVO.FirewallDeviceState;
+import com.cloud.network.resource.PaloAltoResource;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.network.rules.StaticNat;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value = {NetworkElement.class, FirewallServiceProvider.class,
+ PortForwardingServiceProvider.class, IpDeployer.class,
+ SourceNatServiceProvider.class})
+public class PaloAltoExternalFirewallElement extends ExternalFirewallDeviceManagerImpl implements SourceNatServiceProvider, FirewallServiceProvider,
+PortForwardingServiceProvider, IpDeployer, PaloAltoFirewallElementService, StaticNatServiceProvider {
+
+ private static final Logger s_logger = Logger.getLogger(PaloAltoExternalFirewallElement.class);
+
+ private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
+
+ @Inject
+ NetworkModel _networkManager;
+ @Inject
+ HostDao _hostDao;
+ @Inject
+ ConfigurationManager _configMgr;
+ @Inject
+ NetworkOfferingDao _networkOfferingDao;
+ @Inject
+ NetworkDao _networksDao;
+ @Inject
+ DataCenterDao _dcDao;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ ExternalFirewallDeviceDao _fwDevicesDao;
+ @Inject
+ NetworkExternalFirewallDao _networkFirewallDao;
+ @Inject
+ NetworkDao _networkDao;
+ @Inject
+ NetworkServiceMapDao _ntwkSrvcDao;
+ @Inject
+ HostDetailsDao _hostDetailDao;
+ @Inject
+ ConfigurationDao _configDao;
+ @Inject
+ EntityManager _entityMgr;
+
+ private boolean canHandle(Network network, Service service) {
+ DataCenter zone = _entityMgr.findById(DataCenter.class, network.getDataCenterId());
+ if (zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() != Network.GuestType.Isolated) {
+ s_logger.trace("Element " + getProvider().getName() + "is not handling network type = " + network.getGuestType());
+ return false;
+ }
+
+ if (service == null) {
+ if (!_networkManager.isProviderForNetwork(getProvider(), network.getId())) {
+ s_logger.trace("Element " + getProvider().getName() + " is not a provider for the network " + network);
+ return false;
+ }
+ } else {
+ if (!_networkManager.isProviderSupportServiceInNetwork(network.getId(), service, getProvider())) {
+ s_logger.trace("Element " + getProvider().getName() + " doesn't support service " + service.getName() + " in the network " + network);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException, ConcurrentOperationException,
+ InsufficientNetworkCapacityException {
+ DataCenter zone = _entityMgr.findById(DataCenter.class, network.getDataCenterId());
+
+ // don't have to implement network is Basic zone
+ if (zone.getNetworkType() == NetworkType.Basic) {
+ s_logger.debug("Not handling network implement in zone of type " + NetworkType.Basic);
+ return false;
+ }
+
+ if (!canHandle(network, null)) {
+ return false;
+ }
+
+ try {
+ return manageGuestNetworkWithExternalFirewall(true, network);
+ } catch (InsufficientCapacityException capacityException) {
+ // TODO: handle out of capacity exception in more gracefule manner when multiple providers are present for
+ // the network
+ s_logger.error("Fail to implement the Palo Alto for network " + network, capacityException);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean prepare(Network config, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
+ InsufficientNetworkCapacityException, ResourceUnavailableException {
+ return true;
+ }
+
+ @Override
+ public boolean release(Network config, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) {
+ return true;
+ }
+
+ @Override
+ public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ResourceUnavailableException, ConcurrentOperationException {
+ DataCenter zone = _entityMgr.findById(DataCenter.class, network.getDataCenterId());
+
+ // don't have to implement network is Basic zone
+ if (zone.getNetworkType() == NetworkType.Basic) {
+ s_logger.debug("Not handling network shutdown in zone of type " + NetworkType.Basic);
+ return false;
+ }
+
+ if (!canHandle(network, null)) {
+ return false;
+ }
+ try {
+ return manageGuestNetworkWithExternalFirewall(false, network);
+ } catch (InsufficientCapacityException capacityException) {
+ // TODO: handle out of capacity exception
+ return false;
+ }
+ }
+
+ @Override
+ public boolean destroy(Network config, ReservationContext context) {
+ return true;
+ }
+
+ @Override
+ public boolean applyFWRules(Network config, List<? extends FirewallRule> rules) throws ResourceUnavailableException {
+ if (!canHandle(config, Service.Firewall)) {
+ return false;
+ }
+
+ return applyFirewallRules(config, rules);
+ }
+
+ @Override
+ public Provider getProvider() {
+ return Provider.PaloAlto;
+ }
+
+ @Override
+ public Map<Service, Map<Capability, String>> getCapabilities() {
+ return capabilities;
+ }
+
+ private static Map<Service, Map<Capability, String>> setCapabilities() {
+ Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
+
+ // Set capabilities for Firewall service
+ Map<Capability, String> firewallCapabilities = new HashMap<Capability, String>();
+ firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
+ firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp,all");
+ firewallCapabilities.put(Capability.MultipleIps, "true");
+ firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
+ firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress");
+ capabilities.put(Service.Firewall, firewallCapabilities);
+
+ capabilities.put(Service.Gateway, null);
+
+ Map<Capability, String> sourceNatCapabilities = new HashMap<Capability, String>();
+ // Specifies that this element supports either one source NAT rule per account;
+ sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "peraccount");
+ capabilities.put(Service.SourceNat, sourceNatCapabilities);
+
+ // Specifies that port forwarding rules are supported by this element
+ capabilities.put(Service.PortForwarding, null);
+
+ // Specifies that static NAT rules are supported by this element
+ capabilities.put(Service.StaticNat, null);
+
+ return capabilities;
+ }
+
+ @Override
+ public boolean applyPFRules(Network network, List<PortForwardingRule> rules) throws ResourceUnavailableException {
+ if (!canHandle(network, Service.PortForwarding)) {
+ return false;
+ }
+
+ return applyPortForwardingRules(network, rules);
+ }
+
+ @Override
+ public boolean isReady(PhysicalNetworkServiceProvider provider) {
+
+ List<ExternalFirewallDeviceVO> fwDevices = _fwDevicesDao.listByPhysicalNetworkAndProvider(provider.getPhysicalNetworkId(), Provider.PaloAlto.getName());
+ // true if at-least one Palo Alto device is added in to physical network and is in configured (in enabled state) state
+ if (fwDevices != null && !fwDevices.isEmpty()) {
+ for (ExternalFirewallDeviceVO fwDevice : fwDevices) {
+ if (fwDevice.getDeviceState() == FirewallDeviceState.Enabled) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public boolean canEnableIndividualServices() {
+ return true;
+ }
+
+ @Override
+ @Deprecated
+ // should use more generic addNetworkDevice command to add firewall
+ public Host addExternalFirewall(AddExternalFirewallCmd cmd) {
+ Long zoneId = cmd.getZoneId();
+ DataCenterVO zone = null;
+ PhysicalNetworkVO pNetwork = null;
+ HostVO fwHost = null;
+
+ zone = _dcDao.findById(zoneId);
+ if (zone == null) {
+ throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
+ }
+
+ List<PhysicalNetworkVO> physicalNetworks = _physicalNetworkDao.listByZone(zoneId);
+ if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) {
+ throw new InvalidParameterValueException("There are no physical networks or multiple physical networks configured in zone with ID: "
+ + zoneId + " to add this device.");
+ }
+ pNetwork = physicalNetworks.get(0);
+
+ String deviceType = NetworkDevice.PaloAltoFirewall.getName();
+ ExternalFirewallDeviceVO fwDeviceVO = addExternalFirewall(pNetwork.getId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceType, new PaloAltoResource());
+ if (fwDeviceVO != null) {
+ fwHost = _hostDao.findById(fwDeviceVO.getHostId());
+ }
+
+ return fwHost;
+ }
+
+ @Override
+ public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd) {
+ return deleteExternalFirewall(cmd.getId());
+ }
+
+ @Override
+ @Deprecated
+ // should use more generic listNetworkDevice command
+ public List<Host> listExternalFirewalls(ListExternalFirewallsCmd cmd) {
+ List<Host> firewallHosts = new ArrayList<Host>();
+ Long zoneId = cmd.getZoneId();
+ DataCenterVO zone = null;
+ PhysicalNetworkVO pNetwork = null;
+
+ if (zoneId != null) {
+ zone = _dcDao.findById(zoneId);
+ if (zone == null) {
+ throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
+ }
+
+ List<PhysicalNetworkVO> physicalNetworks = _physicalNetworkDao.listByZone(zoneId);
+ if ((physicalNetworks == null) || (physicalNetworks.size() > 1)) {
+ throw new InvalidParameterValueException("There are no physical networks or multiple physical networks configured in zone with ID: "
+ + zoneId + " to add this device.");
+ }
+ pNetwork = physicalNetworks.get(0);
+ }
+
+ firewallHosts.addAll(listExternalFirewalls(pNetwork.getId(), NetworkDevice.PaloAltoFirewall.getName()));
+ return firewallHosts;
+ }
+
+ @Override
+ public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall) {
+ return super.createExternalFirewallResponse(externalFirewall);
+ }
+
+ @Override
+ public List<Class<?>> getCommands() {
+ List<Class<?>> cmdList = new ArrayList<Class<?>>();
+ cmdList.add(AddExternalFirewallCmd.class);
+ cmdList.add(AddPaloAltoFirewallCmd.class);
+ cmdList.add(ConfigurePaloAltoFirewallCmd.class);
+ cmdList.add(DeleteExternalFirewallCmd.class);
+ cmdList.add(DeletePaloAltoFirewallCmd.class);
+ cmdList.add(ListExternalFirewallsCmd.class);
+ cmdList.add(ListPaloAltoFirewallNetworksCmd.class);
+ cmdList.add(ListPaloAltoFirewallsCmd.class);
+ return cmdList;
+ }
+
+ @Override
+ public ExternalFirewallDeviceVO addPaloAltoFirewall(AddPaloAltoFirewallCmd cmd) {
+ String deviceName = cmd.getDeviceType();
+ if (!deviceName.equalsIgnoreCase(NetworkDevice.PaloAltoFirewall.getName())) {
+ throw new InvalidParameterValueException("Invalid Palo Alto firewall device type");
+ }
+ return addExternalFirewall(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName,
+ new PaloAltoResource());
+ }
+
+ @Override
+ public boolean deletePaloAltoFirewall(DeletePaloAltoFirewallCmd cmd) {
+ Long fwDeviceId = cmd.getFirewallDeviceId();
+
+ ExternalFirewallDeviceVO fwDeviceVO = _fwDevicesDao.findById(fwDeviceId);
+ if (fwDeviceVO == null || !fwDeviceVO.getDeviceName().equalsIgnoreCase(NetworkDevice.PaloAltoFirewall.getName())) {
+ throw new InvalidParameterValueException("No Palo Alto firewall device found with ID: " + fwDeviceId);
+ }
+ return deleteExternalFirewall(fwDeviceVO.getHostId());
+ }
+
+ @Override
+ public ExternalFirewallDeviceVO configurePaloAltoFirewall(ConfigurePaloAltoFirewallCmd cmd) {
+ Long fwDeviceId = cmd.getFirewallDeviceId();
+ Long deviceCapacity = cmd.getFirewallCapacity();
+
+ ExternalFirewallDeviceVO fwDeviceVO = _fwDevicesDao.findById(fwDeviceId);
+ if (fwDeviceVO == null || !fwDeviceVO.getDeviceName().equalsIgnoreCase(NetworkDevice.PaloAltoFirewall.getName())) {
+ throw new InvalidParameterValueException("No Palo Alto firewall device found with ID: " + fwDeviceId);
+ }
+
+ if (deviceCapacity != null) {
+ // check if any networks are using this Palo Alto device
+ List<NetworkExternalFirewallVO> networks = _networkFirewallDao.listByFirewallDeviceId(fwDeviceId);
+ if ((networks != null) && !networks.isEmpty()) {
+ if (deviceCapacity < networks.size()) {
+ throw new CloudRuntimeException("There are more number of networks already using this Palo Alto firewall device than configured capacity");
+ }
+ }
+ if (deviceCapacity != null) {
+ fwDeviceVO.setCapacity(deviceCapacity);
+ }
+ }
+
+ fwDeviceVO.setDeviceState(FirewallDeviceState.Enabled);
+ _fwDevicesDao.update(fwDeviceId, fwDeviceVO);
+ return fwDeviceVO;
+ }
+
+ @Override
+ public List<ExternalFirewallDeviceVO> listPaloAltoFirewalls(ListPaloAltoFirewallsCmd cmd) {
+ Long physcialNetworkId = cmd.getPhysicalNetworkId();
+ Long fwDeviceId = cmd.getFirewallDeviceId();
+ PhysicalNetworkVO pNetwork = null;
+ List<ExternalFirewallDeviceVO> fwDevices = new ArrayList<ExternalFirewallDeviceVO>();
+
+ if (physcialNetworkId == null && fwDeviceId == null) {
+ throw new InvalidParameterValueException("Either physical network Id or load balancer device Id must be specified");
+ }
+
+ if (fwDeviceId != null) {
+ ExternalFirewallDeviceVO fwDeviceVo = _fwDevicesDao.findById(fwDeviceId);
+ if (fwDeviceVo == null || !fwDeviceVo.getDeviceName().equalsIgnoreCase(NetworkDevice.PaloAltoFirewall.getName())) {
+ throw new InvalidParameterValueException("Could not find Palo Alto firewall device with ID: " + fwDeviceId);
+ }
+ fwDevices.add(fwDeviceVo);
+ }
+
+ if (physcialNetworkId != null) {
+ pNetwork = _physicalNetworkDao.findById(physcialNetworkId);
+ if (pNetwork == null) {
+ throw new InvalidParameterValueException("Could not find phyical network with ID: " + physcialNetworkId);
+ }
+ fwDevices = _fwDevicesDao.listByPhysicalNetworkAndProvider(physcialNetworkId, Provider.PaloAlto.getName());
+ }
+
+ return fwDevices;
+ }
+
+ @Override
+ public List<? extends Network> listNetworks(ListPaloAltoFirewallNetworksCmd cmd) {
+ Long fwDeviceId = cmd.getFirewallDeviceId();
+ List<NetworkVO> networks = new ArrayList<NetworkVO>();
+
+ ExternalFirewallDeviceVO fwDeviceVo = _fwDevicesDao.findById(fwDeviceId);
+ if (fwDeviceVo == null || !fwDeviceVo.getDeviceName().equalsIgnoreCase(NetworkDevice.PaloAltoFirewall.getName())) {
+ throw new InvalidParameterValueException("Could not find Palo Alto firewall device with ID " + fwDeviceId);
+ }
+
+ List<NetworkExternalFirewallVO> networkFirewallMaps = _networkFirewallDao.listByFirewallDeviceId(fwDeviceId);
+ if (networkFirewallMaps != null && !networkFirewallMaps.isEmpty()) {
+ for (NetworkExternalFirewallVO networkFirewallMap : networkFirewallMaps) {
+ NetworkVO network = _networkDao.findById(networkFirewallMap.getNetworkId());
+ networks.add(network);
+ }
+ }
+
+ return networks;
+ }
+
+ @Override
+ public PaloAltoFirewallResponse createPaloAltoFirewallResponse(ExternalFirewallDeviceVO fwDeviceVO) {
+ PaloAltoFirewallResponse response = new PaloAltoFirewallResponse();
+ Map<String, String> fwDetails = _hostDetailDao.findDetails(fwDeviceVO.getHostId());
+ Host fwHost = _hostDao.findById(fwDeviceVO.getHostId());
+
+ response.setId(fwDeviceVO.getUuid());
+ PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(fwDeviceVO.getPhysicalNetworkId());
+ if (pnw != null) {
+ response.setPhysicalNetworkId(pnw.getUuid());
+ }
+ response.setDeviceName(fwDeviceVO.getDeviceName());
+ if (fwDeviceVO.getCapacity() == 0) {
+ long defaultFwCapacity = NumbersUtil.parseLong(_configDao.getValue(Config.DefaultExternalFirewallCapacity.key()), 50);
+ response.setDeviceCapacity(defaultFwCapacity);
+ } else {
+ response.setDeviceCapacity(fwDeviceVO.getCapacity());
+ }
+ response.setProvider(fwDeviceVO.getProviderName());
+ response.setDeviceState(fwDeviceVO.getDeviceState().name());
+ response.setIpAddress(fwHost.getPrivateIpAddress());
+ response.setPublicInterface(fwDetails.get("publicInterface"));
+ response.setUsageInterface(fwDetails.get("usageInterface"));
+ response.setPrivateInterface(fwDetails.get("privateInterface"));
+ response.setPublicZone(fwDetails.get("publicZone"));
+ response.setPrivateZone(fwDetails.get("privateZone"));
+ response.setNumRetries(fwDetails.get("numRetries"));
+ response.setTimeout(fwDetails.get("timeout"));
+ response.setObjectName("paloaltofirewall");
+ return response;
+ }
+
+ @Override
+ public boolean verifyServicesCombination(Set<Service> services) {
+ if (!services.contains(Service.Firewall)) {
+ s_logger.warn("Palo Alto must be used as Firewall Service Provider in the network");
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public IpDeployer getIpDeployer(Network network) {
+ return this;
+ }
+
+ @Override
+ public boolean applyIps(Network network, List<? extends PublicIpAddress> ipAddress, Set<Service> service) throws ResourceUnavailableException {
+ // return true, as IP will be associated as part of static NAT/port forwarding rule configuration
+ return true;
+ }
+
+ @Override
+ public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException {
+ if (!canHandle(config, Service.StaticNat)) {
+ return false;
+ }
+ return applyStaticNatRules(config, rules);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java
new file mode 100644
index 0000000..d2842ab
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/network/element/PaloAltoFirewallElementService.java
@@ -0,0 +1,88 @@
+// 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.element;
+
+import java.util.List;
+
+import com.cloud.api.commands.AddExternalFirewallCmd;
+import com.cloud.api.commands.AddPaloAltoFirewallCmd;
+import com.cloud.api.commands.ConfigurePaloAltoFirewallCmd;
+import com.cloud.api.commands.DeleteExternalFirewallCmd;
+import com.cloud.api.commands.DeletePaloAltoFirewallCmd;
+import com.cloud.api.commands.ListExternalFirewallsCmd;
+import com.cloud.api.commands.ListPaloAltoFirewallNetworksCmd;
+import com.cloud.api.commands.ListPaloAltoFirewallsCmd;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.host.Host;
+import com.cloud.network.Network;
+import com.cloud.network.dao.ExternalFirewallDeviceVO;
+
+import org.apache.cloudstack.api.response.ExternalFirewallResponse;
+import com.cloud.utils.component.PluggableService;
+
+public interface PaloAltoFirewallElementService extends PluggableService {
+
+ /**
+ * adds a Palo Alto firewall device in to a physical network
+ * @param AddPaloAltoFirewallCmd
+ * @return ExternalFirewallDeviceVO object for the firewall added
+ */
+ public ExternalFirewallDeviceVO addPaloAltoFirewall(AddPaloAltoFirewallCmd cmd);
+
+ /**
+ * removes Palo Alto firewall device from a physical network
+ * @param DeletePaloAltoFirewallCmd
+ * @return true if firewall device successfully deleted
+ */
+ public boolean deletePaloAltoFirewall(DeletePaloAltoFirewallCmd cmd);
+
+ /**
+ * configures a Palo Alto firewal device added in a physical network
+ * @param ConfigurePaloAltoFirewallCmd
+ * @return ExternalFirewallDeviceVO for the device configured
+ */
+ public ExternalFirewallDeviceVO configurePaloAltoFirewall(ConfigurePaloAltoFirewallCmd cmd);
+
+ /**
+ * lists all the Palo Alto firewall devices added in to a physical network
+ * @param ListPaloAltoFirewallsCmd
+ * @return list of ExternalFirewallDeviceVO for the devices in the physical network.
+ */
+ public List<ExternalFirewallDeviceVO> listPaloAltoFirewalls(ListPaloAltoFirewallsCmd cmd);
+
+ /**
+ * lists all the guest networks using a PaloAlto firewall device
+ * @param ListPaloAltoFirewallNetworksCmd
+ * @return list of the guest networks that are using this F5 load balancer
+ */
+ public List<? extends Network> listNetworks(ListPaloAltoFirewallNetworksCmd cmd);
+
+ public PaloAltoFirewallResponse createPaloAltoFirewallResponse(ExternalFirewallDeviceVO fwDeviceVO);
+
+
+ @Deprecated // API helper function supported for backward compatibility
+ public Host addExternalFirewall(AddExternalFirewallCmd cmd);
+
+ @Deprecated // API helper function supported for backward compatibility
+ public boolean deleteExternalFirewall(DeleteExternalFirewallCmd cmd);
+
+ @Deprecated // API helper function supported for backward compatibility
+ public List<Host> listExternalFirewalls(ListExternalFirewallsCmd cmd);
+
+ @Deprecated // API helper function supported for backward compatibility
+ public ExternalFirewallResponse createExternalFirewallResponse(Host externalFirewall);
+}
[5/5] git commit: updated refs/heads/master to 8f8ad3f
Posted by ya...@apache.org.
Squashed commit of the Palo Alto Networks firewall integration plugin.
This patch adds a network plugin to support Palo Alto Networks firewall (their appliance and their VM series firewall).
More information in the FS: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Palo+Alto+Firewall+Integration
Features supported are:
- List/Add/Delete Palo Alto service provider
- List/Add/Delete Palo Alto network service offering
- List/Add/Delete Palo Alto network with above service offering
- Add instance to the new network (creates the public IP and private gateway/cidr on the PA as well as the source nat rule)
- List/Add/Delete Ingress Firewall rule
- List/Add/Delete Egress Firewall rule
- List/Add/Delete Port Forwarding rule
- List/Add/Delete Static Nat rule
- Supports Palo Alto Networks 'Log Forwarding' profile globally per device (additional docs to come)
- Supports Palo Alto Networks 'Security Profile Groups' functionality globally per device (additional docs to come)
Knowns limitations:
- Only supports one public IP range in CloudStack.
- Currently not verifying SSL certificates when creating a connection between CloudStack and the Palo Alto Networks firewall.
- Currently not tracking usage on Public IPs.
Signed-off-by: Sheng Yang <sh...@citrix.com>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8f8ad3f3
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8f8ad3f3
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8f8ad3f3
Branch: refs/heads/master
Commit: 8f8ad3f38ef3c9ee840ba5f86c92d722d2bb5393
Parents: 40a7839
Author: Will Stevens <ws...@cloudops.com>
Authored: Tue Nov 5 22:24:23 2013 -0500
Committer: Sheng Yang <sh...@citrix.com>
Committed: Wed Nov 6 10:08:22 2013 -0800
----------------------------------------------------------------------
api/src/com/cloud/network/Network.java | 1 +
.../admin/network/AddNetworkDeviceCmd.java | 3 +-
.../admin/network/ListNetworkDeviceCmd.java | 2 +-
.../network/ExternalNetworkDeviceManager.java | 1 +
.../classes/resources/messages.properties | 7 +
client/pom.xml | 5 +
client/tomcatconf/commands.properties.in | 11 +
plugins/network-elements/palo-alto/pom.xml | 29 +
.../cloudstack/paloalto/module.properties | 18 +
.../paloalto/spring-paloalto-context.xml | 33 +
.../api/commands/AddExternalFirewallCmd.java | 112 +
.../api/commands/AddPaloAltoFirewallCmd.java | 135 ++
.../commands/ConfigurePaloAltoFirewallCmd.java | 114 +
.../api/commands/DeleteExternalFirewallCmd.java | 88 +
.../api/commands/DeletePaloAltoFirewallCmd.java | 105 +
.../api/commands/ListExternalFirewallsCmd.java | 88 +
.../ListPaloAltoFirewallNetworksCmd.java | 95 +
.../api/commands/ListPaloAltoFirewallsCmd.java | 103 +
.../api/response/PaloAltoFirewallResponse.java | 142 ++
.../PaloAltoExternalFirewallElement.java | 538 +++++
.../element/PaloAltoFirewallElementService.java | 88 +
.../network/resource/PaloAltoResource.java | 2030 ++++++++++++++++++
.../cloud/network/utils/HttpClientWrapper.java | 69 +
.../resource/MockablePaloAltoResource.java | 460 ++++
.../network/resource/PaloAltoResourceTest.java | 507 +++++
plugins/pom.xml | 1 +
server/src/com/cloud/api/ApiResponseHelper.java | 2 +-
.../configuration/ConfigurationManagerImpl.java | 4 +
ui/dictionary.jsp | 7 +
ui/scripts/docs.js | 69 +
ui/scripts/system.js | 572 +++++
31 files changed, 5436 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/api/src/com/cloud/network/Network.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index bda3326..318ac19 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -116,6 +116,7 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
public static final Provider VirtualRouter = new Provider("VirtualRouter", false);
public static final Provider JuniperContrail = new Provider("JuniperContrail", false);
public static final Provider JuniperSRX = new Provider("JuniperSRX", true);
+ public static final Provider PaloAlto = new Provider("PaloAlto", true);
public static final Provider F5BigIp = new Provider("F5BigIp", true);
public static final Provider Netscaler = new Provider("Netscaler", true);
public static final Provider ExternalDhcpServer = new Provider("ExternalDhcpServer", true);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java
index 4983255..a7906f4 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java
@@ -47,8 +47,9 @@ public class AddNetworkDeviceCmd extends BaseCmd {
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
+
@Inject ExternalNetworkDeviceManager nwDeviceMgr;
- @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, description = "Network device type, now supports ExternalDhcp, PxeServer, NetscalerMPXLoadBalancer, NetscalerVPXLoadBalancer, NetscalerSDXLoadBalancer, F5BigIpLoadBalancer, JuniperSRXFirewall")
+ @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, description = "Network device type, now supports ExternalDhcp, PxeServer, NetscalerMPXLoadBalancer, NetscalerVPXLoadBalancer, NetscalerSDXLoadBalancer, F5BigIpLoadBalancer, JuniperSRXFirewall, PaloAltoFirewall")
private String type;
@Parameter(name = ApiConstants.NETWORK_DEVICE_PARAMETER_LIST, type = CommandType.MAP, description = "parameters for network device")
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/api/src/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java
index 0b7836d..5278ba9 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java
@@ -51,7 +51,7 @@ public class ListNetworkDeviceCmd extends BaseListCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, description = "Network device type, now supports ExternalDhcp, PxeServer, NetscalerMPXLoadBalancer, NetscalerVPXLoadBalancer, NetscalerSDXLoadBalancer, F5BigIpLoadBalancer, JuniperSRXFirewall")
+ @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, description = "Network device type, now supports ExternalDhcp, PxeServer, NetscalerMPXLoadBalancer, NetscalerVPXLoadBalancer, NetscalerSDXLoadBalancer, F5BigIpLoadBalancer, JuniperSRXFirewall, PaloAltoFirewall")
private String type;
@Parameter(name = ApiConstants.NETWORK_DEVICE_PARAMETER_LIST, type = CommandType.MAP, description = "parameters for network device")
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java b/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
index 29ce2e3..32f13f8 100644
--- a/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
+++ b/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java
@@ -42,6 +42,7 @@ public interface ExternalNetworkDeviceManager extends Manager {
public static final NetworkDevice NetscalerSDXLoadBalancer = new NetworkDevice("NetscalerSDXLoadBalancer", Network.Provider.Netscaler.getName());
public static final NetworkDevice F5BigIpLoadBalancer = new NetworkDevice("F5BigIpLoadBalancer", Network.Provider.F5BigIp.getName());
public static final NetworkDevice JuniperSRXFirewall = new NetworkDevice("JuniperSRXFirewall", Network.Provider.JuniperSRX.getName());
+ public static final NetworkDevice PaloAltoFirewall = new NetworkDevice("PaloAltoFirewall", Network.Provider.PaloAlto.getName());
public static final NetworkDevice NiciraNvp = new NetworkDevice("NiciraNvp", Network.Provider.NiciraNvp.getName());
public static final NetworkDevice CiscoVnmc = new NetworkDevice("CiscoVnmc", Network.Provider.CiscoVnmc.getName());
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/client/WEB-INF/classes/resources/messages.properties
----------------------------------------------------------------------
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index d548527..e450c29 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -304,6 +304,7 @@ label.add.new.F5=Add new F5
label.add.new.gateway=Add new gateway
label.add.new.NetScaler=Add new NetScaler
label.add.new.SRX=Add new SRX
+label.add.new.PA=Add new Palo Alto
label.add.new.tier=Add new tier
label.add.NiciraNvp.device=Add Nvp Controller
label.add.physical.network=Add physical network
@@ -318,6 +319,7 @@ label.add.secondary.storage=Add Secondary Storage
label.add.security.group=Add Security Group
label.add.service.offering=Add Service Offering
label.add.SRX.device=Add SRX device
+label.add.PA.device=Add Palo Alto device
label.add.static.nat.rule=Add static NAT rule
label.add.static.route=Add static route
label.add.system.service.offering=Add System Service Offering
@@ -479,6 +481,7 @@ label.delete.NetScaler=Delete NetScaler
label.delete.NiciraNvp=Remove Nvp Controller
label.delete.project=Delete project
label.delete.SRX=Delete SRX
+label.delete.PA=Delete Palo Alto
label.delete.VPN.connection=delete VPN connection
label.delete.VPN.customer.gateway=delete VPN Customer Gateway
label.delete.VPN.gateway=delete VPN Gateway
@@ -876,6 +879,8 @@ label.os.type=OS Type
label.owned.public.ips=Owned Public IP Addresses
label.owner.account=Owner Account
label.owner.domain=Owner Domain
+label.PA.log.profile=Palo Alto Log Profile
+label.PA.threat.profile=Palo Alto Threat Profile
label.parent.domain=Parent Domain
label.password.enabled=Password Enabled
label.password=Password
@@ -1048,6 +1053,7 @@ label.specify.vlan=Specify VLAN
label.specify.vxlan=Specify VXLAN
label.SR.name = SR Name-Label
label.srx=SRX
+label.PA=Palo Alto
label.start.IP=Start IP
label.start.port=Start Port
label.start.reserved.system.IP=Start Reserved system IP
@@ -1366,6 +1372,7 @@ message.confirm.action.force.reconnect=Please confirm that you want to force rec
message.confirm.delete.F5=Please confirm that you would like to delete F5
message.confirm.delete.NetScaler=Please confirm that you would like to delete NetScaler
message.confirm.delete.SRX=Please confirm that you would like to delete SRX
+message.confirm.delete.PA=Please confirm that you would like to delete Palo Alto
message.confirm.destroy.router=Please confirm that you would like to destroy this router
message.confirm.disable.provider=Please confirm that you would like to disable this provider
message.confirm.enable.provider=Please confirm that you would like to enable this provider
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index 54cb667..a15a409 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -92,6 +92,11 @@
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloud-plugin-network-palo-alto</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-network-ovs</artifactId>
<version>${project.version}</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 8cbe972..087d8b9 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -533,6 +533,17 @@ configureSrxFirewall=1
listSrxFirewalls=1
listSrxFirewallNetworks=1
+#### Palo Alto firewall commands
+addExternalFirewall=1
+deleteExternalFirewall=1
+listExternalFirewalls=1
+
+addPaloAltoFirewall=1
+deletePaloAltoFirewall=1
+configurePaloAltoFirewall=1
+listPaloAltoFirewalls=1
+listPaloAltoFirewallNetworks=1
+
####Netapp integration commands
createVolumeOnFiler=15
destroyVolumeOnFiler=15
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/pom.xml b/plugins/network-elements/palo-alto/pom.xml
new file mode 100644
index 0000000..50b4c13
--- /dev/null
+++ b/plugins/network-elements/palo-alto/pom.xml
@@ -0,0 +1,29 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>cloud-plugin-network-palo-alto</artifactId>
+ <name>Apache CloudStack Plugin - Palo Alto</name>
+ <parent>
+ <groupId>org.apache.cloudstack</groupId>
+ <artifactId>cloudstack-plugins</artifactId>
+ <version>4.3.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+</project>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/module.properties
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/module.properties b/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/module.properties
new file mode 100644
index 0000000..960fdba
--- /dev/null
+++ b/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/module.properties
@@ -0,0 +1,18 @@
+# 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.
+name=paloalto
+parent=network
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/spring-paloalto-context.xml
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/spring-paloalto-context.xml b/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/spring-paloalto-context.xml
new file mode 100644
index 0000000..251f444
--- /dev/null
+++ b/plugins/network-elements/palo-alto/resources/META-INF/cloudstack/paloalto/spring-paloalto-context.xml
@@ -0,0 +1,33 @@
+<!--
+ 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+ >
+
+ <bean id="PaloAlto" class="com.cloud.network.element.PaloAltoExternalFirewallElement">
+ <property name="name" value="PaloAlto" />
+ </bean>
+</beans>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java
new file mode 100644
index 0000000..84ee869
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddExternalFirewallCmd.java
@@ -0,0 +1,112 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import org.apache.cloudstack.api.response.ExternalFirewallResponse;
+import com.cloud.user.Account;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "addExternalFirewall", description="Adds an external firewall appliance", responseObject = ExternalFirewallResponse.class)
+public class AddExternalFirewallCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(AddExternalFirewallCmd.class.getName());
+ private static final String s_name = "addexternalfirewallresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+ required = true, description="Zone in which to add the external firewall appliance.")
+ private Long zoneId;
+
+ @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external firewall appliance.")
+ private String url;
+
+ @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of the external firewall appliance.")
+ private String username;
+
+ @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Password of the external firewall appliance.")
+ private String password;
+
+ ///////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Inject PaloAltoFirewallElementService _paElementService;
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void execute(){
+ try {
+ Host externalFirewall = _paElementService.addExternalFirewall(this);
+ ExternalFirewallResponse response = _paElementService.createExternalFirewallResponse(externalFirewall);
+ response.setObjectName("externalfirewall");
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } catch (InvalidParameterValueException ipve) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ipve.getMessage());
+ } catch (CloudRuntimeException cre) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, cre.getMessage());
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddPaloAltoFirewallCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddPaloAltoFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddPaloAltoFirewallCmd.java
new file mode 100644
index 0000000..faf28e2
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/AddPaloAltoFirewallCmd.java
@@ -0,0 +1,135 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.dao.ExternalFirewallDeviceVO;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import org.apache.cloudstack.context.CallContext;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "addPaloAltoFirewall", responseObject=PaloAltoFirewallResponse.class, description="Adds a Palo Alto firewall device")
+public class AddPaloAltoFirewallCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(AddPaloAltoFirewallCmd.class.getName());
+ private static final String s_name = "addpaloaltofirewallresponse";
+ @Inject PaloAltoFirewallElementService _paFwService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class,
+ required=true, description="the Physical Network ID")
+ private Long physicalNetworkId;
+
+ @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the Palo Alto appliance.")
+ private String url;
+
+ @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach Palo Alto firewall device")
+ private String username;
+
+ @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach Palo Alto firewall device")
+ private String password;
+
+ @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, required = true, description = "supports only PaloAltoFirewall")
+ private String deviceType;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getPhysicalNetworkId() {
+ return physicalNetworkId;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getDeviceType() {
+ return deviceType;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ ExternalFirewallDeviceVO fwDeviceVO = _paFwService.addPaloAltoFirewall(this);
+ if (fwDeviceVO != null) {
+ PaloAltoFirewallResponse response = _paFwService.createPaloAltoFirewallResponse(fwDeviceVO);
+ response.setObjectName("pafirewall");
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Palo Alto firewall due to internal error.");
+ }
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Adding a Palo Alto firewall device";
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_EXTERNAL_FIREWALL_DEVICE_ADD;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ConfigurePaloAltoFirewallCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ConfigurePaloAltoFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ConfigurePaloAltoFirewallCmd.java
new file mode 100644
index 0000000..199bb83
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ConfigurePaloAltoFirewallCmd.java
@@ -0,0 +1,114 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.dao.ExternalFirewallDeviceVO;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import org.apache.cloudstack.context.CallContext;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "configurePaloAltoFirewall", responseObject=PaloAltoFirewallResponse.class, description="Configures a Palo Alto firewall device")
+public class ConfigurePaloAltoFirewallCmd extends BaseAsyncCmd {
+
+ public static final Logger s_logger = Logger.getLogger(ConfigurePaloAltoFirewallCmd.class.getName());
+ private static final String s_name = "configurepaloaltofirewallresponse";
+ @Inject PaloAltoFirewallElementService _paFwService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.FIREWALL_DEVICE_ID, type=CommandType.UUID, entityType = PaloAltoFirewallResponse.class,
+ required=true, description="Palo Alto firewall device ID")
+ private Long fwDeviceId;
+
+ @Parameter(name=ApiConstants.FIREWALL_DEVICE_CAPACITY, type=CommandType.LONG, required=false, description="capacity of the firewall device, Capacity will be interpreted as number of networks device can handle")
+ private Long capacity;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getFirewallDeviceId() {
+ return fwDeviceId;
+ }
+
+ public Long getFirewallCapacity() {
+ return capacity;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ ExternalFirewallDeviceVO fwDeviceVO = _paFwService.configurePaloAltoFirewall(this);
+ if (fwDeviceVO != null) {
+ PaloAltoFirewallResponse response = _paFwService.createPaloAltoFirewallResponse(fwDeviceVO);
+ response.setObjectName("pafirewall");
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure Palo Alto firewall device due to internal error.");
+ }
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Configuring a Palo Alto firewall device";
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_EXTERNAL_FIREWALL_DEVICE_CONFIGURE;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java
new file mode 100644
index 0000000..93f752a
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeleteExternalFirewallCmd.java
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteExternalFirewall", description="Deletes an external firewall appliance.", responseObject = SuccessResponse.class)
+public class DeleteExternalFirewallCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(DeleteExternalFirewallCmd.class.getName());
+ private static final String s_name = "deleteexternalfirewallresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = HostResponse.class,
+ required = true, description="Id of the external firewall appliance.")
+ private Long id;
+
+ ///////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Inject PaloAltoFirewallElementService _paElementService;
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void execute(){
+ try {
+ boolean result = _paElementService.deleteExternalFirewall(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete external firewall.");
+ }
+ } catch (InvalidParameterValueException e) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Failed to delete external firewall.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeletePaloAltoFirewallCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeletePaloAltoFirewallCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeletePaloAltoFirewallCmd.java
new file mode 100644
index 0000000..8614981
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/DeletePaloAltoFirewallCmd.java
@@ -0,0 +1,105 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import org.apache.cloudstack.context.CallContext;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "deletePaloAltoFirewall", responseObject=SuccessResponse.class, description=" delete a Palo Alto firewall device")
+public class DeletePaloAltoFirewallCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DeletePaloAltoFirewallCmd.class.getName());
+ private static final String s_name = "deletepaloaltofirewallresponse";
+ @Inject PaloAltoFirewallElementService _paElementService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.FIREWALL_DEVICE_ID, type=CommandType.UUID, entityType = PaloAltoFirewallResponse.class,
+ required=true, description="Palo Alto firewall device ID")
+ private Long fwDeviceId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getFirewallDeviceId() {
+ return fwDeviceId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ boolean result = _paElementService.deletePaloAltoFirewall(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete Palo Alto firewall device");
+ }
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Deleting Palo Alto firewall device";
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_EXTERNAL_FIREWALL_DEVICE_DELETE;
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java
new file mode 100644
index 0000000..ebced7e
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListExternalFirewallsCmd.java
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.host.Host;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import org.apache.cloudstack.api.response.ExternalFirewallResponse;
+
+@APICommand(name = "listExternalFirewalls", description="List external firewall appliances.", responseObject = ExternalFirewallResponse.class)
+public class ListExternalFirewallsCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListServiceOfferingsCmd.class.getName());
+ private static final String s_name = "listexternalfirewallsresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class,
+ required = true, description="zone Id")
+ private long zoneId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public long getZoneId() {
+ return zoneId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Inject PaloAltoFirewallElementService _paElementService;
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void execute(){
+
+ List<? extends Host> externalFirewalls = _paElementService.listExternalFirewalls(this);
+
+ ListResponse<ExternalFirewallResponse> listResponse = new ListResponse<ExternalFirewallResponse>();
+ List<ExternalFirewallResponse> responses = new ArrayList<ExternalFirewallResponse>();
+ for (Host externalFirewall : externalFirewalls) {
+ ExternalFirewallResponse response = _paElementService.createExternalFirewallResponse(externalFirewall);
+ response.setObjectName("externalfirewall");
+ response.setResponseName(getCommandName());
+ responses.add(response);
+ }
+
+ listResponse.setResponses(responses);
+ listResponse.setResponseName(getCommandName());
+ this.setResponseObject(listResponse);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallNetworksCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallNetworksCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallNetworksCmd.java
new file mode 100644
index 0000000..15c5bfc
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallNetworksCmd.java
@@ -0,0 +1,95 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.*;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.NetworkResponse;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "listPaloAltoFirewallNetworks", responseObject=NetworkResponse.class, description="lists network that are using Palo Alto firewall device")
+public class ListPaloAltoFirewallNetworksCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger.getLogger(ListPaloAltoFirewallNetworksCmd.class.getName());
+ private static final String s_name = "listpaloaltofirewallnetworksresponse";
+ @Inject PaloAltoFirewallElementService _paFwService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_ID, type=CommandType.UUID, entityType = PaloAltoFirewallResponse.class,
+ required = true, description="palo alto balancer device ID")
+ private Long fwDeviceId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getFirewallDeviceId() {
+ return fwDeviceId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ List<? extends Network> networks = _paFwService.listNetworks(this);
+ ListResponse<NetworkResponse> response = new ListResponse<NetworkResponse>();
+ List<NetworkResponse> networkResponses = new ArrayList<NetworkResponse>();
+
+ if (networks != null && !networks.isEmpty()) {
+ for (Network network : networks) {
+ NetworkResponse networkResponse = _responseGenerator.createNetworkResponse(network);
+ networkResponses.add(networkResponse);
+ }
+ }
+
+ response.setResponses(networkResponses);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallsCmd.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallsCmd.java b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallsCmd.java
new file mode 100644
index 0000000..b788aca
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/commands/ListPaloAltoFirewallsCmd.java
@@ -0,0 +1,103 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.*;
+import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.response.ListResponse;
+import com.cloud.api.response.PaloAltoFirewallResponse;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.dao.ExternalFirewallDeviceVO;
+import com.cloud.network.element.PaloAltoFirewallElementService;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@APICommand(name = "listPaloAltoFirewalls", responseObject=PaloAltoFirewallResponse.class, description="lists Palo Alto firewall devices in a physical network")
+public class ListPaloAltoFirewallsCmd extends BaseListCmd {
+
+ public static final Logger s_logger = Logger.getLogger(ListPaloAltoFirewallsCmd.class.getName());
+ private static final String s_name = "listpaloaltofirewallresponse";
+ @Inject PaloAltoFirewallElementService _paFwService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class,
+ description="the Physical Network ID")
+ private Long physicalNetworkId;
+
+ @Parameter(name=ApiConstants.FIREWALL_DEVICE_ID, type=CommandType.UUID, entityType = PaloAltoFirewallResponse.class,
+ description="Palo Alto firewall device ID")
+ private Long fwDeviceId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getFirewallDeviceId() {
+ return fwDeviceId;
+ }
+
+ public Long getPhysicalNetworkId() {
+ return physicalNetworkId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException {
+ try {
+ List<ExternalFirewallDeviceVO> fwDevices = _paFwService.listPaloAltoFirewalls(this);
+ ListResponse<PaloAltoFirewallResponse> response = new ListResponse<PaloAltoFirewallResponse>();
+ List<PaloAltoFirewallResponse> fwDevicesResponse = new ArrayList<PaloAltoFirewallResponse>();
+
+ if (fwDevices != null && !fwDevices.isEmpty()) {
+ for (ExternalFirewallDeviceVO fwDeviceVO : fwDevices) {
+ PaloAltoFirewallResponse deviceResponse = _paFwService.createPaloAltoFirewallResponse(fwDeviceVO);
+ fwDevicesResponse.add(deviceResponse);
+ }
+ }
+
+ response.setResponses(fwDevicesResponse);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } catch (InvalidParameterValueException invalidParamExcp) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage());
+ } catch (CloudRuntimeException runtimeExcp) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage());
+ }
+ }
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/api/response/PaloAltoFirewallResponse.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/api/response/PaloAltoFirewallResponse.java b/plugins/network-elements/palo-alto/src/com/cloud/api/response/PaloAltoFirewallResponse.java
new file mode 100644
index 0000000..cda018d
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/api/response/PaloAltoFirewallResponse.java
@@ -0,0 +1,142 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api.response;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.EntityReference;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.network.dao.ExternalFirewallDeviceVO;
+
+@EntityReference(value=ExternalFirewallDeviceVO.class)
+@SuppressWarnings("unused")
+public class PaloAltoFirewallResponse extends BaseResponse {
+
+ @SerializedName(ApiConstants.FIREWALL_DEVICE_ID) @Param(description="device id of the Palo Alto firewall")
+ private String id;
+
+ @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this Palo Alto firewall belongs to")
+ private String physicalNetworkId;
+
+ @SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
+ private String providerName;
+
+ @SerializedName(ApiConstants.FIREWALL_DEVICE_NAME) @Param(description="device name")
+ private String deviceName;
+
+ @SerializedName(ApiConstants.FIREWALL_DEVICE_STATE) @Param(description="device state")
+ private String deviceState;
+
+ @SerializedName(ApiConstants.FIREWALL_DEVICE_CAPACITY) @Param(description="device capacity")
+ private Long deviceCapacity;
+
+ @SerializedName(ApiConstants.ZONE_ID) @Param(description="the zone ID of the external firewall")
+ private String zoneId;
+
+ @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the management IP address of the external firewall")
+ private String ipAddress;
+
+ @SerializedName(ApiConstants.USERNAME) @Param(description="the username that's used to log in to the external firewall")
+ private String username;
+
+ @SerializedName(ApiConstants.PUBLIC_INTERFACE) @Param(description="the public interface of the external firewall")
+ private String publicInterface;
+
+ @SerializedName(ApiConstants.USAGE_INTERFACE) @Param(description="the usage interface of the external firewall")
+ private String usageInterface;
+
+ @SerializedName(ApiConstants.PRIVATE_INTERFACE) @Param(description="the private interface of the external firewall")
+ private String privateInterface;
+
+ @SerializedName(ApiConstants.PUBLIC_ZONE) @Param(description="the public security zone of the external firewall")
+ private String publicZone;
+
+ @SerializedName(ApiConstants.PRIVATE_ZONE) @Param(description="the private security zone of the external firewall")
+ private String privateZone;
+
+ @SerializedName(ApiConstants.NUM_RETRIES) @Param(description="the number of times to retry requests to the external firewall")
+ private String numRetries;
+
+ @SerializedName(ApiConstants.TIMEOUT) @Param(description="the timeout (in seconds) for requests to the external firewall")
+ private String timeout;
+
+ public void setId(String lbDeviceId) {
+ this.id = lbDeviceId;
+ }
+
+ public void setPhysicalNetworkId(String physicalNetworkId) {
+ this.physicalNetworkId = physicalNetworkId;
+ }
+
+ public void setProvider(String provider) {
+ this.providerName = provider;
+ }
+
+ public void setDeviceName(String deviceName) {
+ this.deviceName = deviceName;
+ }
+
+ public void setDeviceCapacity(long deviceCapacity) {
+ this.deviceCapacity = deviceCapacity;
+ }
+
+ public void setDeviceState(String deviceState) {
+ this.deviceState = deviceState;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public void setPublicInterface(String publicInterface) {
+ this.publicInterface = publicInterface;
+ }
+
+ public void setUsageInterface(String usageInterface) {
+ this.usageInterface = usageInterface;
+ }
+
+ public void setPrivateInterface(String privateInterface) {
+ this.privateInterface = privateInterface;
+ }
+
+ public void setPublicZone(String publicZone) {
+ this.publicZone = publicZone;
+ }
+
+ public void setPrivateZone(String privateZone) {
+ this.privateZone = privateZone;
+ }
+
+ public String getNumRetries() {
+ return numRetries;
+ }
+
+ public void setNumRetries(String numRetries) {
+ this.numRetries = numRetries;
+ }
+
+ public String getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(String timeout) {
+ this.timeout = timeout;
+ }
+}
[3/5] Squashed commit of the Palo Alto Networks firewall integration
plugin.
Posted by ya...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8f8ad3f3/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java b/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java
new file mode 100644
index 0000000..2251ce0
--- /dev/null
+++ b/plugins/network-elements/palo-alto/src/com/cloud/network/resource/PaloAltoResource.java
@@ -0,0 +1,2030 @@
+// 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.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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 javax.naming.ConfigurationException;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+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.SetFirewallRulesCommand;
+import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+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.rules.FirewallRule;
+import com.cloud.network.rules.FirewallRule.TrafficType;
+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;
+
+// http client handling
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.protocol.HTTP;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.net.URLDecoder;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import com.cloud.network.utils.HttpClientWrapper;
+
+// for prettyFormat()
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import java.io.StringWriter;
+
+public class PaloAltoResource implements ServerResource {
+
+ private String _name;
+ private String _zoneId;
+ private String _ip;
+ private String _username;
+ private String _password;
+ private String _guid;
+ private String _key;
+ private Integer _numRetries;
+ private Integer _timeoutInSeconds;
+ private String _publicZone;
+ private String _privateZone;
+ private String _publicInterface;
+ private String _privateInterface;
+ private String _publicInterfaceType;
+ private String _privateInterfaceType;
+ private String _virtualRouter;
+ private String _threatProfile;
+ private String _logProfile;
+ private String _pingManagementProfile;
+ private final Logger s_logger = Logger.getLogger(PaloAltoResource.class);
+
+ private static String _apiUri = "/api";
+ private static HttpClient _httpclient;
+
+ protected enum PaloAltoMethod {
+ GET, POST;
+ }
+
+ private enum PaloAltoPrimative {
+ CHECK_IF_EXISTS, ADD, DELETE;
+ }
+
+ private enum InterfaceType {
+ AGGREGATE("aggregate-ethernet"),
+ ETHERNET("ethernet");
+
+ private String type;
+
+ private InterfaceType(String type) {
+ this.type = type;
+ }
+ public String toString() {
+ return type;
+ }
+ }
+
+ private enum Protocol {
+ TCP("tcp"),
+ UDP("udp"),
+ ICMP("icmp"),
+ ALL("all");
+
+ private String protocol;
+
+ private Protocol(String protocol) {
+ this.protocol = protocol;
+ }
+ public String toString() {
+ return protocol;
+ }
+ }
+
+ private enum GuestNetworkType {
+ SOURCE_NAT,
+ INTERFACE_NAT;
+ }
+
+ 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 {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+ }
+
+ 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("publicnetwork");
+ if (_publicZone == null) {
+ throw new ConfigurationException("Unable to find public zone");
+ }
+
+ _privateZone = (String) params.get("privatenetwork");
+ if (_privateZone == null) {
+ throw new ConfigurationException("Unable to find private zone");
+ }
+
+ _virtualRouter = (String) params.get("pavr");
+ if (_virtualRouter == null) {
+ throw new ConfigurationException("Unable to find virtual router");
+ }
+
+ _threatProfile = (String) params.get("patp");
+ _logProfile = (String) params.get("palp");
+
+ _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);
+
+ // Open a socket and login
+ if (!refreshPaloAltoConnection()) {
+ throw new ConfigurationException("Unable to open a connection to the Palo Alto.");
+ }
+
+ // check that the threat profile exists if one was specified
+ if (_threatProfile != null) {
+ try {
+ boolean has_profile = getThreatProfile(_threatProfile);
+ if (!has_profile) {
+ throw new ConfigurationException("The specified threat profile group does not exist.");
+ }
+ } catch (ExecutionException e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+ }
+
+ // check that the log profile exists if one was specified
+ if (_logProfile != null) {
+ try {
+ boolean has_profile = getLogProfile(_logProfile);
+ if (!has_profile) {
+ throw new ConfigurationException("The specified log profile does not exist.");
+ }
+ } catch (ExecutionException e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+ }
+
+ // get public interface type
+ try {
+ _publicInterfaceType = getInterfaceType(_publicInterface);
+ if (_publicInterfaceType.equals("")) {
+ throw new ConfigurationException("The specified public interface is not configured on the Palo Alto.");
+ }
+ } catch (ExecutionException e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+
+ // get private interface type
+ try {
+ _privateInterfaceType = getInterfaceType(_privateInterface);
+ if (_privateInterfaceType.equals("")) {
+ throw new ConfigurationException("The specified private interface is not configured on the Palo Alto.");
+ }
+ } catch (ExecutionException e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+
+ _pingManagementProfile = "Ping";
+ try {
+ ArrayList<IPaloAltoCommand> cmdList = new ArrayList<IPaloAltoCommand>();
+ managePingProfile(cmdList, PaloAltoPrimative.ADD);
+ boolean status = requestWithCommit(cmdList);
+ } catch (ExecutionException e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+
+ return true;
+ } catch (Exception e) {
+ throw new ConfigurationException(e.getMessage());
+ }
+
+ }
+
+ public StartupCommand[] initialize() {
+ StartupExternalFirewallCommand cmd = new StartupExternalFirewallCommand();
+ cmd.setName(_name);
+ cmd.setDataCenter(_zoneId);
+ cmd.setPod("");
+ cmd.setPrivateIpAddress(_ip);
+ cmd.setStorageIpAddress("");
+ cmd.setVersion(PaloAltoResource.class.getPackage().getImplementationVersion());
+ cmd.setGuid(_guid);
+ return new StartupCommand[]{cmd};
+ }
+
+ 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() {
+ // nothing for now...
+ }
+
+ public IAgentControl getAgentControl() {
+ return null;
+ }
+
+ public void setAgentControl(IAgentControl agentControl) {
+ return;
+ }
+
+ /*
+ * Login
+ */
+ private void openHttpConnection(){
+ _httpclient = new DefaultHttpClient();
+
+ // Allows you to connect via SSL using unverified certs
+ _httpclient = HttpClientWrapper.wrapClient(_httpclient);
+ }
+
+ private boolean refreshPaloAltoConnection() {
+ if (_httpclient == null) {
+ openHttpConnection();
+ }
+
+ try {
+ return login(_username, _password);
+ } catch (ExecutionException e) {
+ s_logger.error("Failed to login due to " + e.getMessage());
+ return false;
+ }
+ }
+
+ private boolean login(String username, String password) throws ExecutionException {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "keygen");
+ params.put("user", username);
+ params.put("password", password);
+
+ String keygenBody;
+ try {
+ keygenBody = request(PaloAltoMethod.GET, params);
+ } catch (ExecutionException e) {
+ return false;
+ }
+ Document keygen_doc = getDocument(keygenBody);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = xpath.compile("/response[@status='success']/result/key/text()");
+ _key = (String) expr.evaluate(keygen_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (_key != null) {
+ return true;
+ }
+ return false;
+ }
+
+
+ // ENTRY POINTS...
+
+
+ private Answer execute(ReadyCommand cmd) {
+ return new ReadyAnswer(cmd);
+ }
+
+ private Answer execute(MaintainCommand cmd) {
+ return new MaintainAnswer(cmd);
+ }
+
+ private ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) {
+ return new ExternalNetworkResourceUsageAnswer(cmd);
+ }
+
+
+ /*
+ * Guest networks
+ */
+
+ private synchronized Answer execute(IpAssocCommand cmd) {
+ refreshPaloAltoConnection();
+ 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(ip.getBroadcastUri());
+ } catch (Exception e) {
+ throw new ExecutionException("Could not parse public VLAN tag: " + ip.getBroadcastUri());
+ }
+ }
+
+ ArrayList<IPaloAltoCommand> commandList = new ArrayList<IPaloAltoCommand>();
+
+ if (ip.isAdd()) {
+ // Implement the guest network for this VLAN
+ implementGuestNetwork(commandList, type, publicVlanTag, sourceNatIpAddress, guestVlanTag, guestVlanGateway, guestVlanSubnet, cidrSize);
+ } else {
+ // Remove the guest network:
+ shutdownGuestNetwork(commandList, type, publicVlanTag, sourceNatIpAddress, guestVlanTag, guestVlanGateway, guestVlanSubnet, cidrSize);
+ }
+
+ boolean status = requestWithCommit(commandList);
+
+ results[i++] = ip.getPublicIp() + " - success";
+ } catch (ExecutionException e) {
+ s_logger.error(e);
+
+ if (numRetries > 0 && refreshPaloAltoConnection()) {
+ 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(ArrayList<IPaloAltoCommand> cmdList, GuestNetworkType type, Long publicVlanTag, String publicIp, long privateVlanTag, String privateGateway, String privateSubnet, long privateCidrNumber) throws ExecutionException {
+ privateSubnet = privateSubnet+"/"+privateCidrNumber;
+
+ managePrivateInterface(cmdList, PaloAltoPrimative.ADD, privateVlanTag, privateGateway+"/"+privateCidrNumber);
+
+ if (type.equals(GuestNetworkType.SOURCE_NAT)) {
+ managePublicInterface(cmdList, PaloAltoPrimative.ADD, publicVlanTag, publicIp+"/32", privateVlanTag);
+ manageSrcNatRule(cmdList, PaloAltoPrimative.ADD, type, publicVlanTag, publicIp+"/32", privateVlanTag, privateGateway+"/"+privateCidrNumber);
+ manageNetworkIsolation(cmdList, PaloAltoPrimative.ADD, privateVlanTag, privateSubnet, privateGateway);
+ }
+
+ String msg = "Implemented guest network with type " + type + ". Guest VLAN tag: " + privateVlanTag + ", guest gateway: " + privateGateway+"/"+privateCidrNumber;
+ msg += type.equals(GuestNetworkType.SOURCE_NAT) ? ", source NAT IP: " + publicIp : "";
+ s_logger.debug(msg);
+ }
+
+ private void shutdownGuestNetwork(ArrayList<IPaloAltoCommand> cmdList, GuestNetworkType type, Long publicVlanTag, String sourceNatIpAddress, long privateVlanTag, String privateGateway, String privateSubnet, long privateCidrSize) throws ExecutionException {
+ privateSubnet = privateSubnet+"/"+privateCidrSize;
+
+ if (type.equals(GuestNetworkType.SOURCE_NAT)) {
+ manageNetworkIsolation(cmdList, PaloAltoPrimative.DELETE, privateVlanTag, privateSubnet, privateGateway);
+ manageSrcNatRule(cmdList, PaloAltoPrimative.DELETE, type, publicVlanTag, sourceNatIpAddress+"/32", privateVlanTag, privateGateway+"/"+privateCidrSize);
+ managePublicInterface(cmdList, PaloAltoPrimative.DELETE, publicVlanTag, sourceNatIpAddress+"/32", privateVlanTag);
+ }
+
+ managePrivateInterface(cmdList, PaloAltoPrimative.DELETE, privateVlanTag, privateGateway+"/"+privateCidrSize);
+
+ String msg = "Shut down guest network with type " + type +". Guest VLAN tag: " + privateVlanTag + ", guest gateway: " + privateGateway+"/"+privateCidrSize;
+ msg += type.equals(GuestNetworkType.SOURCE_NAT) ? ", source NAT IP: " + sourceNatIpAddress : "";
+ s_logger.debug(msg);
+ }
+
+
+
+ /*
+ * Firewall rule entry point
+ */
+ private synchronized Answer execute(SetFirewallRulesCommand cmd) {
+ refreshPaloAltoConnection();
+ return execute(cmd, _numRetries);
+ }
+
+ private Answer execute(SetFirewallRulesCommand cmd, int numRetries) {
+ FirewallRuleTO[] rules = cmd.getRules();
+ try {
+ ArrayList<IPaloAltoCommand> commandList = new ArrayList<IPaloAltoCommand>();
+
+ for (FirewallRuleTO rule : rules) {
+ if (!rule.revoked()) {
+ manageFirewallRule(commandList, PaloAltoPrimative.ADD, rule);
+ } else {
+ manageFirewallRule(commandList, PaloAltoPrimative.DELETE, rule);
+ }
+ }
+
+ boolean status = requestWithCommit(commandList);
+
+ return new Answer(cmd);
+ } catch (ExecutionException e) {
+ s_logger.error(e);
+
+ if (numRetries > 0 && refreshPaloAltoConnection()) {
+ 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 rule entry point
+ */
+
+ private synchronized Answer execute(SetStaticNatRulesCommand cmd) {
+ refreshPaloAltoConnection();
+ return execute(cmd, _numRetries);
+ }
+
+ private Answer execute(SetStaticNatRulesCommand cmd, int numRetries) {
+ StaticNatRuleTO[] rules = cmd.getRules();
+
+ try {
+ ArrayList<IPaloAltoCommand> commandList = new ArrayList<IPaloAltoCommand>();
+
+ for (StaticNatRuleTO rule : rules) {
+ if (!rule.revoked()) {
+ manageStcNatRule(commandList, PaloAltoPrimative.ADD, rule);
+ } else {
+ manageStcNatRule(commandList, PaloAltoPrimative.DELETE, rule);
+ }
+ }
+
+ boolean status = requestWithCommit(commandList);
+
+ return new Answer(cmd);
+ } catch (ExecutionException e) {
+ s_logger.error(e);
+
+ if (numRetries > 0 && refreshPaloAltoConnection()) {
+ int numRetriesRemaining = numRetries - 1;
+ s_logger.debug("Retrying SetStaticNatRulesCommand. Number of retries remaining: " + numRetriesRemaining);
+ return execute(cmd, numRetriesRemaining);
+ } else {
+ return new Answer(cmd, e);
+ }
+ }
+ }
+
+
+ /*
+ * Destination NAT (Port Forwarding) entry point
+ */
+ private synchronized Answer execute (SetPortForwardingRulesCommand cmd) {
+ refreshPaloAltoConnection();
+ return execute(cmd, _numRetries);
+ }
+
+ private Answer execute(SetPortForwardingRulesCommand cmd, int numRetries) {
+ PortForwardingRuleTO[] rules = cmd.getRules();
+
+ try {
+ ArrayList<IPaloAltoCommand> commandList = new ArrayList<IPaloAltoCommand>();
+
+ for (PortForwardingRuleTO rule : rules) {
+ if (!rule.revoked()) {
+ manageDstNatRule(commandList, PaloAltoPrimative.ADD, rule);
+ } else {
+ manageDstNatRule(commandList, PaloAltoPrimative.DELETE, rule);
+ }
+ }
+
+ boolean status = requestWithCommit(commandList);
+
+ return new Answer(cmd);
+ } catch (ExecutionException e) {
+ s_logger.error(e);
+
+ if (numRetries > 0 && refreshPaloAltoConnection()) {
+ int numRetriesRemaining = numRetries - 1;
+ s_logger.debug("Retrying SetPortForwardingRulesCommand. Number of retries remaining: " + numRetriesRemaining);
+ return execute(cmd, numRetriesRemaining);
+ } else {
+ return new Answer(cmd, e);
+ }
+ }
+ }
+
+
+ // IMPLEMENTATIONS...
+
+
+ /*
+ * Private interface implementation
+ */
+
+ private String genPrivateInterfaceName(long vlanTag) {
+ return _privateInterface+"."+Long.toString(vlanTag);
+ }
+
+ public boolean managePrivateInterface(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, long privateVlanTag, String privateGateway) throws ExecutionException {
+ String interfaceName = genPrivateInterfaceName(privateVlanTag);
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/network/interface/"+_privateInterfaceType+"/entry[@name='"+_privateInterface+"']/layer3/units/entry[@name='"+interfaceName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Private sub-interface exists: "+interfaceName+", "+result);
+ return result;
+
+ case ADD:
+ if (managePrivateInterface(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, privateVlanTag, privateGateway)) {
+ return true;
+ }
+
+ // add cmds
+ // add sub-interface
+ Map<String, String> a_sub_params = new HashMap<String, String>();
+ a_sub_params.put("type", "config");
+ a_sub_params.put("action", "set");
+ a_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_privateInterfaceType+"/entry[@name='"+_privateInterface+"']/layer3/units/entry[@name='"+interfaceName+"']");
+ a_sub_params.put("element", "<tag>"+privateVlanTag+"</tag><ip><entry name='"+privateGateway+"'/></ip><interface-management-profile>"+_pingManagementProfile+"</interface-management-profile>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_sub_params));
+
+ // add sub-interface to VR...
+ Map<String, String> a_vr_params = new HashMap<String, String>();
+ a_vr_params.put("type", "config");
+ a_vr_params.put("action", "set");
+ a_vr_params.put("xpath", "/config/devices/entry/network/virtual-router/entry[@name='"+_virtualRouter+"']/interface");
+ a_vr_params.put("element", "<member>"+interfaceName+"</member>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_vr_params));
+
+ // add sub-interface to vsys...
+ Map<String, String> a_vsys_params = new HashMap<String, String>();
+ a_vsys_params.put("type", "config");
+ a_vsys_params.put("action", "set");
+ a_vsys_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/import/network/interface");
+ a_vsys_params.put("element", "<member>"+interfaceName+"</member>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_vsys_params));
+
+ // add sub-interface to zone...
+ Map<String, String> a_zone_params = new HashMap<String, String>();
+ a_zone_params.put("type", "config");
+ a_zone_params.put("action", "set");
+ a_zone_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/zone/entry[@name='"+_privateZone+"']/network/layer3");
+ a_zone_params.put("element", "<member>"+interfaceName+"</member>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_zone_params));
+
+ return true;
+
+ case DELETE:
+ if (!managePrivateInterface(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, privateVlanTag, privateGateway)) {
+ return true;
+ }
+
+ // add cmds to the list
+ // delete sub-interface from zone...
+ Map<String, String> d_zone_params = new HashMap<String, String>();
+ d_zone_params.put("type", "config");
+ d_zone_params.put("action", "delete");
+ d_zone_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/zone/entry[@name='"+_privateZone+"']/network/layer3/member[text()='"+interfaceName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_zone_params));
+
+ // delete sub-interface from vsys...
+ Map<String, String> d_vsys_params = new HashMap<String, String>();
+ d_vsys_params.put("type", "config");
+ d_vsys_params.put("action", "delete");
+ d_vsys_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/import/network/interface/member[text()='"+interfaceName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_vsys_params));
+
+ // delete sub-interface from VR...
+ Map<String, String> d_vr_params = new HashMap<String, String>();
+ d_vr_params.put("type", "config");
+ d_vr_params.put("action", "delete");
+ d_vr_params.put("xpath", "/config/devices/entry/network/virtual-router/entry[@name='"+_virtualRouter+"']/interface/member[text()='"+interfaceName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_vr_params));
+
+ // delete sub-interface...
+ Map<String, String> d_sub_params = new HashMap<String, String>();
+ d_sub_params.put("type", "config");
+ d_sub_params.put("action", "delete");
+ d_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_privateInterfaceType+"/entry[@name='"+_privateInterface+"']/layer3/units/entry[@name='"+interfaceName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_sub_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+ /*
+ * Public Interface implementation
+ */
+
+ private String genPublicInterfaceName(Long id) {
+ return _publicInterface+"."+Long.toString(id);
+ }
+
+ public boolean managePublicInterface(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, Long publicVlanTag, String publicIp, long privateVlanTag) throws ExecutionException {
+ String interfaceName;
+ if (publicVlanTag == null) {
+ interfaceName = genPublicInterfaceName(new Long("9999"));
+ } else {
+ interfaceName = genPublicInterfaceName(publicVlanTag);
+ }
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+interfaceName+"']/ip/entry[@name='"+publicIp+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Public sub-interface & IP exists: "+interfaceName+" : "+publicIp+", "+result);
+ return result;
+
+ case ADD:
+ if (managePublicInterface(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, publicVlanTag, publicIp, privateVlanTag)) {
+ return true;
+ }
+
+ // add IP to the sub-interface
+ Map<String, String> a_sub_params = new HashMap<String, String>();
+ a_sub_params.put("type", "config");
+ a_sub_params.put("action", "set");
+ a_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+interfaceName+"']/ip");
+ a_sub_params.put("element", "<entry name='"+publicIp+"'/>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_sub_params));
+
+ // add sub-interface to VR (does nothing if already done)...
+ Map<String, String> a_vr_params = new HashMap<String, String>();
+ a_vr_params.put("type", "config");
+ a_vr_params.put("action", "set");
+ a_vr_params.put("xpath", "/config/devices/entry/network/virtual-router/entry[@name='"+_virtualRouter+"']/interface");
+ a_vr_params.put("element", "<member>"+interfaceName+"</member>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_vr_params));
+
+ // add sub-interface to vsys (does nothing if already done)...
+ Map<String, String> a_vsys_params = new HashMap<String, String>();
+ a_vsys_params.put("type", "config");
+ a_vsys_params.put("action", "set");
+ a_vsys_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/import/network/interface");
+ a_vsys_params.put("element", "<member>"+interfaceName+"</member>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_vsys_params));
+
+ // add sub-interface to zone (does nothing if already done)...
+ Map<String, String> a_zone_params = new HashMap<String, String>();
+ a_zone_params.put("type", "config");
+ a_zone_params.put("action", "set");
+ a_zone_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/zone/entry[@name='"+_publicZone+"']/network/layer3");
+ a_zone_params.put("element", "<member>"+interfaceName+"</member>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_zone_params));
+
+ return true;
+
+ case DELETE:
+ if (!managePublicInterface(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, publicVlanTag, publicIp, privateVlanTag)) {
+ return true;
+ }
+
+ // delete IP from sub-interface...
+ Map<String, String> d_sub_params = new HashMap<String, String>();
+ d_sub_params.put("type", "config");
+ d_sub_params.put("action", "delete");
+ d_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+interfaceName+"']/ip/entry[@name='"+publicIp+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_sub_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+ /*
+ * Source NAT rule implementation
+ */
+
+ private String genSrcNatRuleName(Long privateVlanTag) {
+ return "src_nat."+Long.toString(privateVlanTag);
+ }
+
+ public boolean manageSrcNatRule(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, GuestNetworkType type, Long publicVlanTag, String publicIp, long privateVlanTag, String privateGateway) throws ExecutionException {
+ String publicInterfaceName;
+ if (publicVlanTag == null) {
+ publicInterfaceName = genPublicInterfaceName(new Long("9999"));
+ } else {
+ publicInterfaceName = genPublicInterfaceName(publicVlanTag);
+ }
+ String srcNatName = genSrcNatRuleName(privateVlanTag);
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+srcNatName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Source NAT exists: "+srcNatName+", "+result);
+ return result;
+
+ case ADD:
+ if (manageSrcNatRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, type, publicVlanTag, publicIp, privateVlanTag, privateGateway)) {
+ return true;
+ }
+
+ String xml = "";
+ xml += "<from><member>"+_privateZone+"</member></from>";
+ xml += "<to><member>"+_publicZone+"</member></to>";
+ xml += "<source><member>"+privateGateway+"</member></source>";
+ xml += "<destination><member>any</member></destination>";
+ xml += "<service>any</service>";
+ xml += "<nat-type>ipv4</nat-type>";
+ xml += "<to-interface>"+publicInterfaceName+"</to-interface>";
+ xml += "<source-translation><dynamic-ip-and-port><interface-address>";
+ xml += "<ip>"+publicIp+"</ip>";
+ xml += "<interface>"+publicInterfaceName+"</interface>";
+ xml += "</interface-address></dynamic-ip-and-port></source-translation>";
+
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+srcNatName+"']");
+ a_params.put("element", xml);
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!manageSrcNatRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, type, publicVlanTag, publicIp, privateVlanTag, privateGateway)) {
+ return true;
+ }
+
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+srcNatName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, d_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+ /*
+ * Destination NAT rules (Port Forwarding) implementation
+ */
+ private String genDstNatRuleName(String publicIp, long id) {
+ return "dst_nat."+genIpIdentifier(publicIp)+"_"+Long.toString(id);
+ }
+
+ public boolean manageDstNatRule(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, PortForwardingRuleTO rule) throws ExecutionException {
+ String publicIp = rule.getSrcIp();
+ String dstNatName = genDstNatRuleName(publicIp, rule.getId());
+
+ String publicInterfaceName;
+ String publicVlanTag = rule.getSrcVlanTag();
+ if (publicVlanTag == null || publicVlanTag.equals("untagged")) {
+ publicInterfaceName = genPublicInterfaceName(new Long("9999"));
+ } else {
+ publicInterfaceName = genPublicInterfaceName(new Long(publicVlanTag));
+ }
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+dstNatName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Destination NAT exists: "+dstNatName+", "+result);
+ return result;
+
+ case ADD:
+ if (manageDstNatRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, rule)) {
+ return true;
+ }
+
+ // build source service xml
+ String srcService;
+ String protocol = rule.getProtocol();
+ int[] srcPortRange = rule.getSrcPortRange();
+ if (srcPortRange != null) {
+ String portRange;
+ if (srcPortRange.length == 1 || srcPortRange[0] == srcPortRange[1]) {
+ portRange = String.valueOf(srcPortRange[0]);
+ } else {
+ portRange = String.valueOf(srcPortRange[0])+"-"+String.valueOf(srcPortRange[1]);
+ }
+ manageService(cmdList, PaloAltoPrimative.ADD, protocol, portRange, null);
+ srcService = genServiceName(protocol, portRange, null);
+ } else {
+ // no equivalent config in PA, so allow all traffic...
+ srcService = "any";
+ }
+
+ // build destination port xml (single port limit in PA)
+ String dstPortXML = "";
+ int[] dstPortRange = rule.getDstPortRange();
+ if (dstPortRange != null) {
+ dstPortXML = "<translated-port>"+dstPortRange[0]+"</translated-port>";
+ }
+
+ // add public IP to the sub-interface
+ Map<String, String> a_sub_params = new HashMap<String, String>();
+ a_sub_params.put("type", "config");
+ a_sub_params.put("action", "set");
+ a_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+publicInterfaceName+"']/ip");
+ a_sub_params.put("element", "<entry name='"+publicIp+"/32'/>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_sub_params));
+
+ // add the destination nat rule for the public IP
+ String xml = "";
+ xml += "<from><member>"+_publicZone+"</member></from>";
+ xml += "<to><member>"+_publicZone+"</member></to>";
+ xml += "<source><member>any</member></source>";
+ xml += "<destination><member>"+publicIp+"</member></destination>";
+ xml += "<service>"+srcService+"</service>";
+ xml += "<nat-type>ipv4</nat-type>";
+ xml += "<to-interface>"+publicInterfaceName+"</to-interface>";
+ xml += "<destination-translation><translated-address>"+rule.getDstIp()+"</translated-address>"+dstPortXML+"</destination-translation>";
+
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+dstNatName+"']");
+ a_params.put("element", xml);
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!manageDstNatRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, rule)) {
+ return true;
+ }
+
+ // determine if we need to delete the ip from the interface as well...
+ Map<String, String> c_params = new HashMap<String, String>();
+ c_params.put("type", "config");
+ c_params.put("action", "get");
+ c_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[destination/member[text()='"+publicIp+"']]");
+ String c_response = request(PaloAltoMethod.GET, c_params);
+
+ String count = "";
+ NodeList response_body;
+ Document doc = getDocument(c_response);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = xpath.compile("/response[@status='success']/result");
+ response_body = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (response_body.getLength() > 0 && response_body.item(0).getAttributes().getLength() > 0) {
+ count = response_body.item(0).getAttributes().getNamedItem("count").getTextContent();
+ }
+
+ // delete the dst nat rule
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+dstNatName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, d_params));
+
+ if (!count.equals("") && Integer.parseInt(count) == 1) { // this dst nat rule is the last, so remove the ip...
+ // delete IP from sub-interface...
+ Map<String, String> d_sub_params = new HashMap<String, String>();
+ d_sub_params.put("type", "config");
+ d_sub_params.put("action", "delete");
+ d_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+publicInterfaceName+"']/ip/entry[@name='"+publicIp+"/32']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_sub_params));
+ }
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+
+ /*
+ * Static NAT rule implementation
+ */
+ private String genStcNatRuleName(String publicIp, long id) {
+ return "stc_nat."+genIpIdentifier(publicIp)+"_"+Long.toString(id);
+ }
+
+ public boolean manageStcNatRule(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, StaticNatRuleTO rule) throws ExecutionException {
+ String publicIp = rule.getSrcIp();
+ String stcNatName = genStcNatRuleName(publicIp, rule.getId());
+
+ String publicInterfaceName;
+ String publicVlanTag = rule.getSrcVlanTag();
+ if (publicVlanTag == null || publicVlanTag.equals("untagged")) {
+ publicInterfaceName = genPublicInterfaceName(new Long("9999"));
+ } else {
+ publicInterfaceName = genPublicInterfaceName(new Long(publicVlanTag));
+ }
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+stcNatName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Static NAT exists: "+stcNatName+", "+result);
+ return result;
+
+ case ADD:
+ if (manageStcNatRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, rule)) {
+ return true;
+ }
+
+ // add public IP to the sub-interface
+ Map<String, String> a_sub_params = new HashMap<String, String>();
+ a_sub_params.put("type", "config");
+ a_sub_params.put("action", "set");
+ a_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+publicInterfaceName+"']/ip");
+ a_sub_params.put("element", "<entry name='"+publicIp+"/32'/>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_sub_params));
+
+ // add the static nat rule for the public IP
+ String xml = "";
+ xml += "<from><member>"+_publicZone+"</member></from>";
+ xml += "<to><member>"+_publicZone+"</member></to>";
+ xml += "<source><member>any</member></source>";
+ xml += "<destination><member>"+publicIp+"</member></destination>";
+ xml += "<service>any</service>";
+ xml += "<nat-type>ipv4</nat-type>";
+ xml += "<to-interface>"+publicInterfaceName+"</to-interface>";
+ xml += "<destination-translation><translated-address>"+rule.getDstIp()+"</translated-address></destination-translation>";
+
+
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+stcNatName+"']");
+ a_params.put("element", xml);
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!manageStcNatRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, rule)) {
+ return true;
+ }
+
+ // delete the static nat rule
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/nat/rules/entry[@name='"+stcNatName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, d_params));
+
+ // delete IP from sub-interface...
+ Map<String, String> d_sub_params = new HashMap<String, String>();
+ d_sub_params.put("type", "config");
+ d_sub_params.put("action", "delete");
+ d_sub_params.put("xpath", "/config/devices/entry/network/interface/"+_publicInterfaceType+"/entry[@name='"+_publicInterface+"']/layer3/units/entry[@name='"+publicInterfaceName+"']/ip/entry[@name='"+publicIp+"/32']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_sub_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+ /*
+ * Firewall rule implementation
+ */
+
+ private String genFirewallRuleName(long id) {
+ return "policy_"+Long.toString(id);
+ }
+
+ public boolean manageFirewallRule(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, FirewallRuleTO rule) throws ExecutionException {
+ String ruleName = genFirewallRuleName(rule.getId());
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='"+ruleName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Firewall policy exists: "+ruleName+", "+result);
+ return result;
+
+ case ADD:
+ if (manageFirewallRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, rule)) {
+ return true;
+ }
+
+ String srcZone;
+ String dstZone;
+ String dstAddressXML;
+ String appXML;
+ String serviceXML;
+
+ String protocol = rule.getProtocol();
+
+ // Only ICMP will use an Application, so others will be any.
+ if (protocol.equals(Protocol.ICMP.toString())) {
+ appXML = "<member>icmp</member><member>ping</member><member>traceroute</member>"; // use the default icmp applications...
+ } else {
+ appXML = "<member>any</member>";
+ }
+
+ // Only TCP and UDP will use a Service, others will use any.
+ if (protocol.equals(Protocol.TCP.toString()) || protocol.equals(Protocol.UDP.toString())) {
+ String portRange;
+ if (rule.getSrcPortRange() != null) {
+ int startPort = rule.getSrcPortRange()[0];
+ int endPort = rule.getSrcPortRange()[1];
+ if (startPort == endPort) {
+ portRange = String.valueOf(startPort);
+ } else {
+ portRange = String.valueOf(startPort)+"-"+String.valueOf(endPort);
+ }
+ manageService(cmdList, PaloAltoPrimative.ADD, protocol, portRange, null);
+ serviceXML = "<member>"+genServiceName(protocol, portRange, null)+"</member>";
+ } else {
+ // no equivalent config in PA, so allow all traffic...
+ serviceXML = "<member>any</member>";
+ }
+ } else {
+ serviceXML = "<member>any</member>";
+ }
+
+ if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) { // Network egress rule
+ srcZone = _privateZone;
+ dstZone = _publicZone;
+ dstAddressXML = "<member>any</member>";
+ } else {
+ srcZone = _publicZone;
+ dstZone = _privateZone;
+ dstAddressXML = "<member>"+rule.getSrcIp()+"</member>";
+ }
+
+ // build the source cidr xml
+ String srcCidrXML = "";
+ List<String> ruleSrcCidrList = rule.getSourceCidrList();
+ if (ruleSrcCidrList.size() > 0) { // a cidr was entered, modify as needed...
+ for (int i = 0; i < ruleSrcCidrList.size(); i++) {
+ if (ruleSrcCidrList.get(i).trim().equals("0.0.0.0/0")) { // allow any
+ if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) {
+ srcCidrXML += "<member>"+getPrivateSubnet(rule.getSrcVlanTag())+"</member>";
+ } else {
+ srcCidrXML += "<member>any</member>";
+ }
+ } else {
+ srcCidrXML += "<member>"+ruleSrcCidrList.get(i).trim()+"</member>";
+ }
+ }
+ } else { // no cidr was entered, so allow ALL according to firewall rule type
+ if (rule.getTrafficType() == FirewallRule.TrafficType.Egress) {
+ srcCidrXML = "<member>"+getPrivateSubnet(rule.getSrcVlanTag())+"</member>";
+ } else {
+ srcCidrXML = "<member>any</member>";
+ }
+ }
+
+ String xml = "";
+ xml += "<from><member>"+srcZone+"</member></from>";
+ xml += "<to><member>"+dstZone+"</member></to>";
+ xml += "<source>"+srcCidrXML+"</source>";
+ xml += "<destination>"+dstAddressXML+"</destination>";
+ xml += "<application>"+appXML+"</application>";
+ xml += "<service>"+serviceXML+"</service>";
+ xml += "<action>allow</action>";
+ xml += "<negate-source>no</negate-source>";
+ xml += "<negate-destination>no</negate-destination>";
+ if (_threatProfile != null) { // add the threat profile if it exists
+ xml += "<profile-setting><group><member>"+_threatProfile+"</member></group></profile-setting>";
+ }
+ if (_logProfile != null) { // add the log profile if it exists
+ xml += "<log-setting>"+_logProfile+"</log-setting>";
+ }
+
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='"+ruleName+"']");
+ a_params.put("element", xml);
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!manageFirewallRule(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, rule)) {
+ return true;
+ }
+
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='"+ruleName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, d_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+
+ /*
+ * Usage
+ */
+
+
+
+ /*
+ * Helper config functions
+ */
+
+ // ensure guest network isolation
+ private String genNetworkIsolationName(long privateVlanTag) {
+ return "isolate_"+Long.toString(privateVlanTag);
+ }
+
+ public boolean manageNetworkIsolation(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, long privateVlanTag, String privateSubnet, String privateGateway) throws ExecutionException {
+ String ruleName = genNetworkIsolationName(privateVlanTag);
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='"+ruleName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Firewall policy exists: "+ruleName+", "+result);
+ return result;
+
+ case ADD:
+ if (manageNetworkIsolation(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, privateVlanTag, privateSubnet, privateGateway)) {
+ return true;
+ }
+
+ String xml = "";
+ xml += "<from><member>"+_privateZone+"</member></from>";
+ xml += "<to><member>"+_privateZone+"</member></to>";
+ xml += "<source><member>"+privateSubnet+"</member></source>";
+ xml += "<destination><member>"+privateGateway+"</member></destination>";
+ xml += "<application><member>any</member></application>";
+ xml += "<service><member>any</member></service>";
+ xml += "<action>deny</action>";
+ xml += "<negate-source>no</negate-source>";
+ xml += "<negate-destination>yes</negate-destination>";
+
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='"+ruleName+"']");
+ a_params.put("element", xml);
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!manageNetworkIsolation(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, privateVlanTag, privateSubnet, privateGateway)) {
+ return true;
+ }
+
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='"+ruleName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.POST, d_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+ // make the interfaces pingable for basic network troubleshooting
+ public boolean managePingProfile(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim) throws ExecutionException {
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/network/profiles/interface-management-profile/entry[@name='"+_pingManagementProfile+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Management profile exists: "+_pingManagementProfile+", "+result);
+ return result;
+
+ case ADD:
+ if (managePingProfile(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS)) {
+ return true;
+ }
+
+ // add ping profile...
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/network/profiles/interface-management-profile/entry[@name='"+_pingManagementProfile+"']");
+ a_params.put("element", "<ping>yes</ping>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!managePingProfile(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS)) {
+ return true;
+ }
+
+ // delete ping profile...
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/network/profiles/interface-management-profile/entry[@name='"+_pingManagementProfile+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+
+ private String genServiceName(String protocol, String dstPorts, String srcPorts) {
+ String name;
+ if (srcPorts == null) {
+ name = "cs_"+protocol.toLowerCase()+"_"+dstPorts.replace(',', '.');
+ } else {
+ name = "cs_"+protocol.toLowerCase()+"_"+dstPorts.replace(',', '.')+"_"+srcPorts.replace(',', '.');
+ }
+ return name;
+ }
+
+ public boolean manageService(ArrayList<IPaloAltoCommand> cmdList, PaloAltoPrimative prim, String protocol, String dstPorts, String srcPorts) throws ExecutionException {
+ String serviceName = genServiceName(protocol, dstPorts, srcPorts);
+
+ switch (prim) {
+
+ case CHECK_IF_EXISTS:
+ // check if one exists already
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/service/entry[@name='"+serviceName+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ boolean result = (validResponse(response) && responseNotEmpty(response));
+ s_logger.debug("Service exists: "+serviceName+", "+result);
+ return result;
+
+ case ADD:
+ if (manageService(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, protocol, dstPorts, srcPorts)) {
+ return true;
+ }
+
+ String dstPortXML = "<port>"+dstPorts+"</port>";
+ String srcPortXML = "";
+ if (srcPorts != null) {
+ srcPortXML = "<source-port>"+srcPorts+"</source-port>";
+ }
+
+ // add ping profile...
+ Map<String, String> a_params = new HashMap<String, String>();
+ a_params.put("type", "config");
+ a_params.put("action", "set");
+ a_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/service/entry[@name='"+serviceName+"']");
+ a_params.put("element", "<protocol><"+protocol.toLowerCase()+">"+dstPortXML+srcPortXML+"</"+protocol.toLowerCase()+"></protocol>");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, a_params));
+
+ return true;
+
+ case DELETE:
+ if (!manageService(cmdList, PaloAltoPrimative.CHECK_IF_EXISTS, protocol, dstPorts, srcPorts)) {
+ return true;
+ }
+
+ // delete ping profile...
+ Map<String, String> d_params = new HashMap<String, String>();
+ d_params.put("type", "config");
+ d_params.put("action", "delete");
+ d_params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/service/entry[@name='"+serviceName+"']");
+ cmdList.add(new DefaultPaloAltoCommand(PaloAltoMethod.GET, d_params));
+
+ return true;
+
+ default:
+ s_logger.debug("Unrecognized command.");
+ return false;
+ }
+ }
+
+ private String getPrivateSubnet(String vlan) throws ExecutionException {
+ String _interfaceName = genPrivateInterfaceName(Long.valueOf(vlan).longValue());
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/network/interface/"+_privateInterfaceType+"/entry[@name='"+_privateInterface+"']/layer3/units/entry[@name='"+_interfaceName+"']/ip/entry");
+ String response = request(PaloAltoMethod.GET, params);
+ if (validResponse(response) && responseNotEmpty(response)) {
+ NodeList response_body;
+ Document doc = getDocument(response);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = xpath.compile("/response[@status='success']/result/entry");
+ response_body = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (response_body.getLength() > 0) {
+ return response_body.item(0).getAttributes().getNamedItem("name").getTextContent();
+ }
+ }
+ return null;
+ }
+
+
+ /*
+ * XML API commands
+ */
+
+ /* Function to make calls to the Palo Alto API. */
+ /* All API calls will end up going through this function. */
+ protected String request(PaloAltoMethod method, Map<String, String> params) throws ExecutionException {
+ if (method != PaloAltoMethod.GET && method != PaloAltoMethod.POST) {
+ throw new ExecutionException("Invalid http method used to access the Palo Alto API.");
+ }
+
+ String responseBody = "";
+ String debug_msg = "Palo Alto Request\n";
+
+ // a GET method...
+ if (method == PaloAltoMethod.GET) {
+ String queryString = "?";
+ for (String key : params.keySet()) {
+ if (!queryString.equals("?")) {
+ queryString = queryString + "&";
+ }
+ try {
+ queryString = queryString + key+"="+URLEncoder.encode(params.get(key), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+ if (_key != null) {
+ queryString = queryString + "&key="+_key;
+ }
+
+ try {
+ debug_msg = debug_msg + "GET request: https://" + _ip + _apiUri + URLDecoder.decode(queryString, "UTF-8") + "\n";
+ } catch (UnsupportedEncodingException e) {
+ debug_msg = debug_msg + "GET request: https://" + _ip + _apiUri + queryString + "\n";
+ }
+
+
+ HttpGet get_request = new HttpGet("https://" + _ip + _apiUri + queryString);
+ ResponseHandler<String> responseHandler = new BasicResponseHandler();
+ try {
+ responseBody = _httpclient.execute(get_request, responseHandler);
+ } catch (IOException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ // a POST method...
+ if (method == PaloAltoMethod.POST) {
+ List <NameValuePair> nvps = new ArrayList <NameValuePair>();
+ for (String key : params.keySet()) {
+ nvps.add(new BasicNameValuePair(key, params.get(key)));
+ }
+ if (_key != null) {
+ nvps.add(new BasicNameValuePair("key", _key));
+ }
+
+ debug_msg = debug_msg + "POST request: https://" + _ip + _apiUri + "\n";
+ for (NameValuePair nvp : nvps) {
+ debug_msg = debug_msg + "param: "+nvp.getName()+", "+nvp.getValue() + "\n";
+ }
+
+ HttpPost post_request = new HttpPost("https://" + _ip + _apiUri);
+ try {
+ post_request.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
+ } catch (UnsupportedEncodingException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ ResponseHandler<String> responseHandler = new BasicResponseHandler();
+ try {
+ responseBody = _httpclient.execute(post_request, responseHandler);
+ } catch (IOException e) {
+ throw new ExecutionException(e.getMessage());
+ }
+ }
+
+ debug_msg = debug_msg + prettyFormat(responseBody);
+ debug_msg = debug_msg + "\n" + responseBody.replace("\"", "\\\"") + "\n\n"; // test cases
+ //s_logger.debug(debug_msg); // this can be commented if we don't want to show each request in the log.
+
+ return responseBody;
+ }
+
+ /* Used for requests that require polling to get a result (eg: commit) */
+ private String requestWithPolling(PaloAltoMethod method, Map<String, String> params) throws ExecutionException {
+ String job_id;
+ String job_response = request(method, params);
+ Document doc = getDocument(job_response);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = xpath.compile("/response[@status='success']/result/job/text()");
+ job_id = (String) expr.evaluate(doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (job_id.length() > 0) {
+ boolean finished = false;
+ Map<String, String> job_params = new HashMap<String, String>();
+ job_params.put("type", "op");
+ job_params.put("cmd", "<show><jobs><id>"+job_id+"</id></jobs></show>");
+
+ while (!finished) {
+ String job_status;
+ String response = request(PaloAltoMethod.GET, job_params);
+ Document job_doc = getDocument(response);
+ XPath job_xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = job_xpath.compile("/response[@status='success']/result/job/status/text()");
+ job_status = (String) expr.evaluate(job_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (job_status.equals("FIN")) {
+ finished = true;
+ String job_result;
+ try {
+ XPathExpression expr = job_xpath.compile("/response[@status='success']/result/job/result/text()");
+ job_result = (String) expr.evaluate(job_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (!job_result.equals("OK")) {
+ NodeList job_details;
+ try {
+ XPathExpression expr = job_xpath.compile("/response[@status='success']/result/job/details/line");
+ job_details = (NodeList) expr.evaluate(job_doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ String error = "";
+ for (int i = 0; i < job_details.getLength(); i++) {
+ error = error + job_details.item(i).getTextContent() + "\n";
+ }
+ throw new ExecutionException(error);
+ }
+ return response;
+ } else {
+ try {
+ Thread.sleep(2000); // poll periodically for the status of the async job...
+ } catch (InterruptedException e) { /* do nothing */ }
+ }
+ }
+ } else {
+ return job_response;
+ }
+ return null;
+ }
+
+ /* Runs a sequence of commands and attempts to commit at the end. */
+ /* Uses the Command pattern to enable overriding of the response handling if needed. */
+ private synchronized boolean requestWithCommit(ArrayList<IPaloAltoCommand> commandList) throws ExecutionException {
+ boolean result = true;
+
+ if (commandList.size() > 0) {
+ // CHECK IF THERE IS PENDING CHANGES THAT HAVE NOT BEEN COMMITTED...
+ String pending_changes;
+ Map<String, String> check_params = new HashMap<String, String>();
+ check_params.put("type", "op");
+ check_params.put("cmd", "<check><pending-changes></pending-changes></check>");
+ String check_response = request(PaloAltoMethod.GET, check_params);
+ Document check_doc = getDocument(check_response);
+ XPath check_xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = check_xpath.compile("/response[@status='success']/result/text()");
+ pending_changes = (String) expr.evaluate(check_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (pending_changes.equals("yes")) {
+ throw new ExecutionException("The Palo Alto has uncommited changes, so no changes can be made. Try again later or contact your administrator.");
+ } else {
+ // ADD A CONFIG LOCK TO CAPTURE THE PALO ALTO RESOURCE
+ String add_lock_status;
+ Map<String, String> add_lock_params = new HashMap<String, String>();
+ add_lock_params.put("type", "op");
+ add_lock_params.put("cmd", "<request><config-lock><add></add></config-lock></request>");
+ String add_lock_response = request(PaloAltoMethod.GET, add_lock_params);
+ Document add_lock_doc = getDocument(add_lock_response);
+ XPath add_lock_xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = add_lock_xpath.compile("/response[@status='success']/result/text()");
+ add_lock_status = (String) expr.evaluate(add_lock_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (add_lock_status.length() == 0) {
+ throw new ExecutionException("The Palo Alto is locked, no changes can be made at this time.");
+ }
+
+ try {
+ // RUN THE SEQUENCE OF COMMANDS
+ for (IPaloAltoCommand command : commandList) {
+ result = (result && command.execute()); // run commands and modify result boolean
+ }
+
+ // COMMIT THE CHANGES (ALSO REMOVES CONFIG LOCK)
+ String commit_job_id;
+ Map<String, String> commit_params = new HashMap<String, String>();
+ commit_params.put("type", "commit");
+ commit_params.put("cmd", "<commit></commit>");
+ String commit_response = requestWithPolling(PaloAltoMethod.GET, commit_params);
+ Document commit_doc = getDocument(commit_response);
+ XPath commit_xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = commit_xpath.compile("/response[@status='success']/result/job/id/text()");
+ commit_job_id = (String) expr.evaluate(commit_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (commit_job_id.length() == 0) { // no commit was done, so release the lock...
+ // REMOVE THE CONFIG LOCK TO RELEASE THE PALO ALTO RESOURCE
+ String remove_lock_status;
+ Map<String, String> remove_lock_params = new HashMap<String, String>();
+ remove_lock_params.put("type", "op");
+ remove_lock_params.put("cmd", "<request><config-lock><remove></remove></config-lock></request>");
+ String remove_lock_response = request(PaloAltoMethod.GET, remove_lock_params);
+ Document remove_lock_doc = getDocument(remove_lock_response);
+ XPath remove_lock_xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = remove_lock_xpath.compile("/response[@status='success']/result/text()");
+ remove_lock_status = (String) expr.evaluate(remove_lock_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (remove_lock_status.length() == 0) {
+ throw new ExecutionException("Could not release the Palo Alto device. Please notify an administrator!");
+ }
+ }
+
+ } catch (ExecutionException ex) {
+ // REVERT TO RUNNING
+ String revert_job_id;
+ Map<String, String> revert_params = new HashMap<String, String>();
+ revert_params.put("type", "op");
+ revert_params.put("cmd", "<load><config><from>running-config.xml</from></config></load>");
+ requestWithPolling(PaloAltoMethod.GET, revert_params);
+
+ // REMOVE THE CONFIG LOCK TO RELEASE THE PALO ALTO RESOURCE
+ String remove_lock_status;
+ Map<String, String> remove_lock_params = new HashMap<String, String>();
+ remove_lock_params.put("type", "op");
+ remove_lock_params.put("cmd", "<request><config-lock><remove></remove></config-lock></request>");
+ String remove_lock_response = request(PaloAltoMethod.GET, remove_lock_params);
+ Document remove_lock_doc = getDocument(remove_lock_response);
+ XPath remove_lock_xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = remove_lock_xpath.compile("/response[@status='success']/result/text()");
+ remove_lock_status = (String) expr.evaluate(remove_lock_doc, XPathConstants.STRING);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (remove_lock_status.length() == 0) {
+ throw new ExecutionException("Could not release the Palo Alto device. Please notify an administrator!");
+ }
+
+ throw ex; // Bubble up the reason we reverted...
+ }
+
+ return result;
+ }
+ } else {
+ return true; // nothing to do
+ }
+ }
+
+ /* A default response handler to validate that the request was successful. */
+ public boolean validResponse(String response) throws ExecutionException {
+ NodeList response_body;
+ Document doc = getDocument(response);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = xpath.compile("/response[@status='success']");
+ response_body = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+
+ if (response_body.getLength() > 0) {
+ return true;
+ } else {
+ NodeList error_details;
+ try {
+ XPathExpression expr = xpath.compile("/response/msg/line/line");
+ error_details = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ if (error_details.getLength() == 0) {
+ try {
+ XPathExpression expr = xpath.compile("/response/msg/line");
+ error_details = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+
+ if (error_details.getLength() == 0) {
+ try {
+ XPathExpression expr = xpath.compile("/response/result/msg");
+ error_details = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+ }
+ }
+ String error = "";
+ for (int i = 0; i < error_details.getLength(); i++) {
+ error = error + error_details.item(i).getTextContent() + "\n";
+ }
+ throw new ExecutionException(error);
+ }
+ }
+
+ /* Validate that the response is not empty. */
+ public boolean responseNotEmpty(String response) throws ExecutionException {
+ NodeList response_body;
+ Document doc = getDocument(response);
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ try {
+ XPathExpression expr = xpath.compile("/response[@status='success']");
+ response_body = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+ } catch (XPathExpressionException e) {
+ throw new ExecutionException(e.getCause().getMessage());
+ }
+
+ if (response_body.getLength() > 0 &&
+ (!response_body.item(0).getTextContent().equals("") ||
+ (response_body.item(0).hasChildNodes() && response_body.item(0).getFirstChild().hasChildNodes()))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /* Get the type of interface from the PA device. */
+ private String getInterfaceType(String interface_name) throws ExecutionException {
+ String[] types = { InterfaceType.ETHERNET.toString(), InterfaceType.AGGREGATE.toString() };
+ for (String type : types) {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/network/interface/"+type+"/entry[@name='"+interface_name+"']");
+ String ethernet_response = request(PaloAltoMethod.GET, params);
+ if (validResponse(ethernet_response) && responseNotEmpty(ethernet_response)) {
+ return type;
+ }
+ }
+ return "";
+ }
+
+ /* Get the threat profile from the server if it exists. */
+ private boolean getThreatProfile(String profile) throws ExecutionException {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/profile-group/entry[@name='"+profile+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ return (validResponse(response) && responseNotEmpty(response));
+ }
+
+ /* Get the log profile from the server if it exists. */
+ private boolean getLogProfile(String profile) throws ExecutionException {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("type", "config");
+ params.put("action", "get");
+ params.put("xpath", "/config/devices/entry/vsys/entry[@name='vsys1']/log-settings/profiles/entry[@name='"+profile+"']");
+ String response = request(PaloAltoMethod.GET, params);
+ return (validResponse(response) && responseNotEmpty(response));
+ }
+
+ /* Command Interface */
+ public interface IPaloAltoCommand {
+ public boolean execute() throws ExecutionException;
+ }
+
+ /* Command Abstract */
+ private abstract class AbstractPaloAltoCommand implements IPaloAltoCommand {
+ PaloAltoMethod method;
+ Map<String, String> params;
+
+ public AbstractPaloAltoCommand() {}
+
+ public AbstractPaloAltoCommand(PaloAltoMethod method, Map<String, String> params) {
+ this.method = method;
+ this.params = params;
+ }
+
+ public boolean execute() throws ExecutionException {
+ String response = request(method, params);
+ return validResponse(response);
+ }
+ }
+
+ /* Implement the default functionality */
+ private class DefaultPaloAltoCommand extends AbstractPaloAltoCommand {
+ public DefaultPaloAltoCommand(PaloAltoMethod method, Map<String, String> params) {
+ super(method, params);
+ }
+ }
+
+
+ /*
+ * Misc
+ */
+
+ private String genIpIdentifier(String ip) {
+ return ip.r
<TRUNCATED>