Chapter 2: Starting Coding

This chapter starts examining coding examples which make use of the InControl API.

Similarities with the CLI

A useful principle to remember is that programming with the InControl API is very similar to constructing cOS Core Command Line Interface (CLI) commands. The two are similar since they both interact with the Configuration Engine which is the cOS Core subsystem that deals with the management of cOS Core configurations.

Similarities to the CLI will be discussed further in this guide and example CLI commands will sometimes be given following InControl API based code in order to highlight the similarities. The CLI Reference Guide can be an extremely useful reference document when programming with the API since it lists all possible API parameter options.

A key difference between using the CLI and the InControl API is that an equivalent to the "cc" (change context/category) command does not need to be used to change the current context to be a particular object such as the main IP rule set when editing IP rules. Instead, the InControl API uses a more direct way of referring to a particular configuration object.

A Simple Example

A simple first example of API based source code can be found below. This example, like others used throughout this guide, is written in the C Sharp (C#) language and assumes that the development environment is setup accordingly with references to the WCF service (see Appendix A, Visual Studio Setup).

The example's assumptions are:

// Define the address for the connection
	
EndpointAddress epa =
   new EndpointAddress("http://icserver.mycompany.com:8080/InControl");

// Create the binding

WSHttpBinding wsHttpBinding = new WSHttpBinding(SecurityMode.Message);
wsHttpBinding.Security.Message.ClientCredentialType =
		MessageCredentialType.Windows;
wsHttpBinding.Security.Message.EstablishSecurityContext = true;

// Get the security element for adding the parameter requirements

BindingElementCollection bec = wsHttpBinding.CreateBindingElements();
SecurityBindingElement sbe = bec.Find<SecurityBindingElement>();
if (sbe == null) {
  throw new InvalidOperationException("No SecurityBindingElement found!");
}

// Add the parameter requirements

sbe.EndpointSupportingTokenParameters.SignedEncrypted.Add(
		new UserNameSecurityTokenParameters());
		
// Create the binding
		
CustomBinding cb = new CustomBinding(bec);

// Create the client

ChannelFactory<InControl_API.IRemoteServer> cf =
		new ChannelFactory<InControl_API.IRemoteServer>(cb, epa);

// Specify the client credentials

cf.Credentials.UserName.UserName = "MyUsername";
cf.Credentials.UserName.Password = "MyPassword";

// Retrieve the server object

IRemoteServer server = cf.CreateChannel();

// Increase the timeout to 3 seconds from the default of 1
// This may be required by the "DeployConfiguration" function
		
((IContextChannel)server).OperationTimeout = new TimeSpan(0, 3, 0);

// Get the root domain which contains all defined security gateways

Domain global = server.get_Root();

// Assume there is a device in the root domain called 'sgwStockholm'
// Get this security gateway

Device sgwStockholm =
	server.GetConfigObjectByName(global, "sgwStockholm") as Device; 

// Check out this security gateway

server.CheckOutConfiguration(sgwStockholm);

// Get the latest configuration for this gateway

Configuration cfg = server.GetLatestConfiguration(sgwStockholm);

// Add a new IP rule
// Start by setting the properties of the rule

Dictionary<string, string> properties = new Dictionary<string, string>();

properties.Add("Action", "NAT");
properties.Add("SourceInterface", "lan");
properties.Add("SourceNetwork", "lannet");
properties.Add("DestinationInterface", "wan");
properties.Add("DestinationNetwork","all-nets");
properties.Add("Service", "http-outbound");
properties.Add("LogEnabled", "True");
properties.Add("Comments", "Allow and NAT HTTP traffic from LAN to WAN");

// Get the main IPRuleSet folder for adding nodes
// Note how the rule set identifier is constructed

Node folder = server.GetRootNode(cfg);

// Add the IP Rule as a child node to this folder
 
server.AddChildNode(folder, "IPRule", "NAT_HTTP", properties);

// Check in the new configuration

server.CheckInConfiguration(cfg,
		"Added IP rule allowing NAT LAN to WAN HTTP traffic");

// Deploy and activate the new configuration on the security gateway

server.DeployConfiguration(sgwStockholm);

// Finished so close the connection to the InControl server

(server as IClientChannel).Close();
[Note] Note

Error handling try and catch blocks are not explicitly shown in these code examples. However, they should be used and follow normal error handling practices to catch any errors.

Connection Using net.tcp

An alternative to using HTTP/SOAP is to use net.tcp as the connection protocol. Assuming that the URL for the server is net.tcp://localhost:33726/InControl, the connection code up until getting the IRemoteServer object instance is as follows:

// Define the address for the connection
	
EndpointAddress epa =
		new EndpointAddress("net.tcp://localhost:33726/InControl");

// Create the binding

NetTcpBinding netTcpBinding = new NetTcpBinding(SecurityMode.Message);
netTcpBinding.Security.Message.ClientCredentialType =
		MessageCredentialType.Windows;

// Get the security element for adding the parameter requirements

BindingElementCollection bec = netTcpBinding.CreateBindingElements();
SecurityBindingElement sbe = bec.Find<SecurityBindingElement>();
if (sbe == null) {
  throw new InvalidOperationException("No SecurityBindingElement found!");
}

// Add the parameter requirements

sbe.EndpointSupportingTokenParameters.SignedEncrypted.Add(
		new UserNameSecurityTokenParameters());
		
// Create the binding
		
CustomBinding cb = new CustomBinding(bec);

// Create the client

ChannelFactory<InControl_API.IRemoteServer> cf =
		new ChannelFactory<InControl_API.IRemoteServer>(cb, epa);

// Specify the client credentials

cf.Credentials.UserName.UserName = "MyUsername";
cf.Credentials.UserName.Password = "MyPassword";

// Retrieve the server object

IRemoteServer server = cf.CreateChannel();

// Increase the timeout if required for deployment
		
((IContextChannel)cf).OperationTimeout = new TimeSpan(0, 3, 0);

The above code is identical to the HTTP/SOAP code from adding the parameter requirements onwards.

Reasons for using and Not Using net.tcp

There are a number of reasons for using and not using net.tcp instead of HTTP/SOAP :

Adding a Security Gateway

The simplest case when adding a security gateway is adding a single standalone gateway below the global domain object. To make the following examples concise, it will be assumed that an IRemoteServer server object with the name server has already been retrieved.

// Assume the security keys for all gateways are the following:
 String keys="DBC2A65220E2D3753149EDED524FC1A140CDA6810FA68E2A78F4FC1A1";
	
// First, get the global domain object
Domain global = server.get_Root();

// Add the security gateway called MySGW
Guid sgwId = server.AddSecurityGateway("MySGW", global.Id,
			"192.168.1.222", 999, keys, "Add gateway via API");

Deleting a Security Gateway

Deletion of a gateway is done in a similar way to deleting any other object.

// Get the object for the device
Device mySGW = server.GetConfigObjectById(null, sgwId) as Device;

// Delete the object
server.DeleteConfigObject(mySGW, true);

Adding a High Availability Cluster

The procedure to add an HA cluster involves first adding the cluster object and then adding the gateways to that.

// Get the root object for the global domain
Domain global = server.get_Root();

// Add a cluster under the root object
Guid clusterId = server.AddCluster("MyCluster",
			global.Id, 0, 0, "Add Cluster via API");

// Add the cluster master
Guid master = server.AddSecurityGateway("cluster_master", clusterId,
			"192.168.1.123", 999, keys, "Add master via API");

// Add the cluster slave
Guid master = server.AddSecurityGateway("cluster_slave", clusterId,
			"192.168.1.124", 999, keys, "Add slave via API");
	

Deleting a High Availability Cluster

In order to delete an HA cluster, the individual gateways must first be deleted and then the cluster itself is deleted.

// Delete the cluster master
Device master_device = server.GetConfigObjectById(null,masterId) as Device;
server.DeleteConfigObject(master_device, true);

// Delete the cluster slave
Device master_device = server.GetConfigObjectById(null,slaveId) as Device;
server.DeleteConfigObject(master_device, true);

// Delete the cluster itself
Cluster myCluster = server.GetConfigObjectById(null,clusterId) as Cluster;
server.DeleteConfigObject(myCluster, true);