Automated Coder

Exploring the Code of CruiseControl.Net

Posts Tagged ‘Communications’

Reducing Strings: Transferring Data

Posted by Craig Sutherland on 29 November, 2009

A Multi-OS Challenge

CruiseControl.NET has gone through a few iterations of file transfer. Prior to version 1.4, the only files that could be transferred was the build log and other special files like the statistics or RSS feed. To handle these files there were special methods in the Remote API, and all they did was transfer the entire file across the network as a single string (serialised via .NET Remoting).

With CruiseControl.NET 1.4 we added the ability to transfer any file that was located in the artefacts folder of a project. This was a new method in the Remote API, but it now allowed the remote client to ask for a file. If the file was there, it was transferred across the web. And this is where things got interesting!

Originally, this method generated a MarshalByRef-based object that would connect back to the server and transfer the data a block at a time. This ensured that only small blocks of data were transferred, thus reducing the memory usage on the server.

Unfortunately Windows 2008 did not like this approach! IPSec blocked the object from connecting back to the server, so no data was transferred (yes, it worked on every other OS we tried, just one that stopped it.) After several frustrating attempts to resolve the issue, we gave up and went to transferring the entire file as a single byte[] buffer over the network. Once again memory usage went up :-(

So, for CruiseControl 2.0 we are back to the issue of how can we transfer large files across the network?

Let’s Chat

The problem with transferring a single large block of data across the network is it needs to be loaded into memory first, and then transferred across the network. Even .NET Remoting does not like transferring large blocks across the network, but it does it. Under the hood .NET Remoting takes the large block of data and breaks it into smaller blocks, which then get transferred across the network. This is what our original approach did, but IPSec did not like it!

So, how can we go back to the block-based approach and get past IPSec? The answer is to move from our nice chunky interface, were .NET Remoting handles the blocks, to a more chatty interface (yes, I know, normally not a good practise, but sometimes we don’t live in an ideal world!)

The current situation looks something like this:

image

With .NET Remoting handling the blocking within the red arrow. The new approach will look like this:

image

Yes, it will be a multi-step approach. The steps are:

  1. Open the file on the server
  2. Transfer each block of data
  3. Close the file on the server

This approach requires tighter coupling between the client and the server (sigh). When the client opens the file, a file identifier if returned. This file identifier is what the client then passes to the server for all subsequent operations.

So, why a file identifier? The identifier is used to identify which instance of the opened file is being used (the file is opened in read-mode so it can be opened multiple times). The server then maps the identifier to the stream instance (which is only held on the server). When each block is transferred, the stream is repositioned so the next block is ready. This means the client does not care where it is in the process, it only cares that there is more data to fetch.

The other downside for this approach is the file now needs to be closed on the server – other the number of open streams will slowly increase (i.e. a memory leak!) So closing the file will clean up after the transfer has been completed.

The other approach I looked at was for the client to pass in the starting position. But in the end I decided against this approach for two reasons:

  1. It would require the client know what data it wanted (i.e. the position within the file). If it requested a position beyond the file length, then the server would need some error handling to not fail.
  2. It would require opening the file, positioning to the correct location and closing the file every data fetch! I’m not sure on the performance of this, but it sounds slow.

Of course, if we run into issues with my current approach we can switch to the alternate and test it out, but for now, it’s the approach we are using :-)

Being Helpful

Now, rather than forcing the clients to implement their own versions of file transfer (and potentially duplicate their code), I’ve added a new method to CruiseServerClient in the Remote API. This method is called TransferFile() and it literally does that – it handles all the logic of transferring a file from the server into a local stream.

To use this method is as simple as the following code:

client.TransferFile(projectName, fileName, outputStream);

Where client is an instance of CruiseServerClient (this can be generated from a CruiseServerClientFactory).

I have gone through and removed the old file transfer mechanism (in both the web dashboard and CCTray) and changed to using this method. This means all file transfers will now use the new approach and use less memory. However in a future post I’ll do some tests to see how much (if any) memory is being saved.

Coming Up

Now that we have a file transfer mechanism, the next step is to look at handling the new build log format. In my next post (or posts) I’ll look at the modifications to retrieve the build data and the changes to the dashboard.

Stay tuned…

Posted in CruiseControl.Net, Project Ares | Tagged: , , , | Leave a Comment »

Reducing Strings: A Quick Look Back

Posted by Craig Sutherland on 24 November, 2009

Where Have We Come From?

Before I start modifying the remote interfaces to use the new stream-based data storage, I thought I’d take a quick look back at the memory performance of these interfaces. Again I’ll be using ANTS Memory Profiler 5 to look at how memory is being used.

Just to show the impact of strings in the system I’ll take a look at the original system before I added caching, and then after to see what impact this change had. These will then provide the baselines for looking at how the stream changes can reduce the memory footprint of the CruiseControl.NET server.

But before I get into the analysis, let’s revise how data is sent from the server to a client (e.g. CCTray, the dashboard, etc.) The entire build log is stored in a single file on disk. The client makes a request to the server via .NET Remoting. This then opens the file, reads it all into memory and returns the entire file back to the client as a string. The caching changes modify this procedure only by ensuring there is a single instance of each build log in memory – subsequent calls to retrieve the same log will use the cached log (note, this is cached in memory).

The Method

This is not as nice and tidy as testing the memory usage for a project. The server needs to be up and running and the client then makes the call to the server. However since we are not interested in the client memory usage (yet), we need to be monitoring the server and we cannot directly tell when a memory usage scenario is beginning. To get around this limitation I wrote a small application (stress client) that makes multiple calls to the server to fetch the latest build log for a project. The build log I am fetching is 6Mb in size, the application will attempt to download this log concurrently multiple times to give the profiler plenty of attempts to analyse. On my memory I was able to get four concurrent instances connecting at once, each instance fetched the same build log ten times.

With this in place, I started the profiler and started profiling the server (ccnet.exe). This was run without any start-up parameters and left running for the duration at the test. I waited 30 seconds after starting the application and after the test had finished to make sure the relevant data was collected. After the 30 seconds for start-up had passed I ran the stress client and waited for it to finished. 30 seconds after the client had finished I shut down the server. I performed two sets of tests. The first set of tests I just ran the profiler and collected the memory stats. The second set of tests I captured the memory usage every 5-10 seconds during the test (this was done manually).

These tests were run three times, with the following versions:

  1. This is the original CruiseControl.NET server before the caching was added
  2. This is CruiseControl.NET server with caching added
  3. This is CruiseControl.NET server with caching added, plus an extra modification to garbage collect after each build log fetch

The 1.5.0 codebase was used for all three versions. Only the get build log method was modified for each version.

The Data

These are the results from the original version (#1):

Run1

For the original version, just accessing the build log allocated 234Mb of memory to the server – of which most is used by the large object heap.

Changing to the modified version of the server we get the following results:

Run2

The first thing to notice is the private bytes is also half the original version – and the large object heap is very flat. In the original version a new string was added to the heap every time a client accessed the build log, in the new version there is only one version – hence the reason for the heap being much flatter. However the application is still using a lot of memory – there is a total of 80Mb assigned to all the heaps.

So, the final change is to force garbage collection:

Run3

Again, there is a drastic reduction in memory – this time there is only a maximum of 40MB in all heaps – and the total memory allocated has also been reduced. However, looking at the large object heap, there has been no change – so the question is what has changed and why?

Digging Deeper

The ANTS memory profiler has the ability to take a snapshot of what is currently being used by an application. This shows what objects have been allocated and what is associated with what. The only down side is the snapshots have to be manually taken, but the graphs help to show where snapshots need to be taken. These snapshots can then be viewed in the application to see where the memory is being used and what is holding onto the memory.

For this analysis I only took snapshots of versions 2 and 3 to see exactly what was using memory. Version 2 showed the following information:

Memory-1

While version 3 showed the following:

Memory-2

This shows that string and byte[] has the most memory usage in both versions, but it is the amount of byte[] memory that has changed. The following shows why this is the case:

byte-data

The remoting infrastructure is generating blocks of byte[] data (byte[4096] to be exact) which are then being transmitted to the client. When the data is returned to the client the remoting infrastructure is breaking it down into blocks of byte[] data, these are what then get sent over the wire. These blocks are only 4096b in size, so they are not stored on the large object heap, but the large number of them (4,800 in the example for version 2) means they are taking up a large amount of space. So, in order to reduce memory usage we also need to look into this area also. This is important to note, because in CruiseControl.NET 1.5.0 (and earlier versions) all data transfer is handled by sending a single block of data. We did try during the development of 1.5.0 to do a block transfer, but IPSec in Win2K8 blocked it, so we had to reverse the changes. So we need to find a permanent solution to this issue that will work on all OS versions!

In Summary

We had a quick look at memory consumption under 1.5.0 seeing what could be done to reduce the amount of memory usage. However we’ve pretty much run into a stumbling block with the current log size and that it is a single (huge) block of data. For CruiseControl.NET 2.0 we have already split the build log into smaller files, but we also need to look at what can be done to reduce memory usage while transferring over the wire.

So, in my next post I’ll take a look at an alternate transfer mechanism. Stay tuned…

Posted in CruiseControl.Net, Project Ares | Tagged: , , | Leave a Comment »

Monitor – a High Level API

Posted by Craig Sutherland on 18 July, 2009

Introduction

Recently I’ve been playing around with some client applications for CruiseControl.NET (more on this in a later post). As I was coding, I realised it is not that easy to work with entities for CruiseControl.NET. Yes, there is a new communications library that simplifies the communications, but it still requires a knowledge of which method does what.

It would be nice if there were some high level entities that simplify this process and hides all the method calls. Additionally, it would be nice if these entities stayed up-to-date with the actual server. This would be useful in a number of places – including both CCTray and the dashboard.

So I sat down and put together a high level API. This is built on top of the communications library – so under the hood it just uses the messaging. But it does abstract away these details – instead of calling the communications API and passing in the correct parameters, you just initialise the Monitor API and then use the entities returned.

Before I continue, I should mention, this is my first cut of it. I have been trialling it out and it “kind-of” works, but it is still very rough around the edges. Of course, this will only be relevant to you if you are interested in developing applications to communicate with the CruiseControl.NET server.

The API

The API exposes four entities (currently):

Monitor Classes

These classes expose most of the information about the current status of the server. When I say current, I mean as of the last snapshot taken of the server. They don’t include historical details (yet).

The Server class provides a high-level overview of the server. Currently, this only lists the projects and the servers that are available, but it does provide notifications of when projects or queues are added or removed from the server. Additionally, this is the root level class for the API. To interact with the API you will need to create an instance of this class – more on this later.

The Project class provides details on the current status of a project. This is all taken from the snapshot method, so it doesn’t include historical details. It does contain all the details that are currently available in CCTray or the projects grid of the dashboard (e.g. current status, current activity, next and previous build times, etc.)

The BuildQueue class does the same for an integration queue, although there are less details available for a queue. It does expose an array of BuildQueueRequest instances, which contains details on each current or pending request for the queue.

These four classes are all tied together, which eliminates some of the problems we have in CCTray. For example, in the Module API, it is easy to find out which server a project belong to, as there is a direct relationship between the two (Project has a property called Server, which points to the Server instance).

Additionally, there are a number of helper methods (with more to come). If you need to build a project, there is a method called ForceBuild() which does exactly that. under the hood, these methods call the communications API to pass the requests onto the server, but someone using the Monitor API does not need to know this.

Events and Monitoring

One of the key parts of the Monitor API is change notifications. The API can be configured so it automatically monitors the server (hence the reason for its name). When the server changes (e.g. adding/removing a project/queue, a project starting building, etc.) an event is triggered.

Most of the classes implement INotifyPropertyChanged, so a PropertyChanged event will be fired when a property on the server changes. There is also a new set of events for when a project, build queue or build queue request is added or removed.

This makes it easy for a client to detect any changes – just initialise the Server instance with a polling watcher and the events will be fired automatically. This makes it incredibly easy to set up applications that “watch” a server and do things when the server changes.

Some Examples

Rather than go into the details of how the API works, I thought I’d finish off with some examples so people can see how it works.

First of all, to initialise the API, a new server instance needs to be created. Since this relies on the communications API underneath, it needs an instance of CruiseServerClientBase. The following shows how to initialise  the client and then the server:

  1: var client = factory.GenerateClient(clientAddress);
  2: var server = new Server(client);
  3: server.Refresh()

The first line creates the new client instance, the second then creates the server instance. The third line is not strictly necessary, but it will force a refresh of the data from the server (otherwise it will wait until the server is polled).

Once the server is initialised, it is easy to work with both projects and queues. There are both Projects and BuildQueues properties to list all of the projects and queues. Alternately, if you know which project or queue is needed, there are FindProject() and FindBuildQueue() methods to search by name. For example, to force a build on a project you could use the following code:

  1: var project = server.FindProject("CruiseControl.NET");
  2: project.ForceBuild();

Finally, here is an example of how to register an event for watching a status change:

  1: var project = server.FindProject("CruiseControl.NET");
  2: project.PropertyChanged += (o, e) => {
  3:     if (e.PropertyName == "Status") {
  4:         // Do something for a status change
  5:     }
  6: };

And for a new build request on a queue:

  1: var queue = server.FindBuildQueue("CruiseControl.NET");
  2: queue.BuildQueueRequestAdded += (o, e) => {
  3:     // Do something when a new build request is queued
  4: };

Of course, these are just some of the things that can be done, plus I should mention that there are still a lot of things that cannot be done (at least not directly).

Where To Next?

Over time I’m planning on expanding the API to cover a lot more tasks. Initially I plan on including all the information and tasks that are available in CCTray 1.5.0. Most of this has already been done, but I still need to include status breakdowns and package lists.

Once this is feature complete, I’ll start looking at how to include historical data – previous build results, history and statistics, etc. This will cover most of the information that is available in the dashboard.

At the same time I am working on a little side project that is using the new Monitor API. This has mainly been a test bed for concept, which I’m looking at releasing as a separate project (more on this later on).

Once the API is complete and useful, I might (and I’ll stress the “might” part) convert both CCTray and the dashboard to use it. This would certainly simplify a lot of the “horrible” code in these two clients. The bad news is it getting harder to work with these two clients, and trying to unwind all the complexities around communications is challenging (hence the reason for some of the existing bugs!)

In Conclusion

Hopefully, this gives an idea of what can be done with the new Monitor API, and also some of its current limitations. Over time I’m planning on expanding it to provide any necessary information from CruiseControl.NET, by which time it should be easy to build clients for the system.

And finally, I have a surprise coming, although it’s not completely new news.

Stay tuned…

Posted in CruiseControl.Net | Tagged: | 2 Comments »

The Missing Piece: Encrypted Communications

Posted by Craig Sutherland on 15 July, 2009

Introduction

In my last post (read it here) I wrote about an issue with security – that the actual communications between the client and the server were not secure. I also outlined the approach I was taking to remedy the issue.

Before I move onto my solution, I must mention that this is not a perfect solution. As one of my readers commented, this does not really cover a man-in-the-middle attack. It will prevent network sniffing and replay attacks, it is still possible to insert a listener between the client and the server.

It is possible to configure .NET Remoting to intrinsically secure communications – in which case there is no need to worry about this from the client side at all. However, it is not easy easy as it might appear, so I decided to finish my partial solution.

In time, I hope to be able to look at expanding the communications channels. Currently the only channel for communicating with the server is .NET Remoting – which was because of the way methods used to be called. Now with the new messaging-based framework, it is easier to add new channels. Hopefully I will get some time to look at using SslStream and NegotiateStream to secure communications.

Client Communications

First, how does the new code send encrypted messages to the server? This involved expanding how messages are currently sent.

Currently messaging uses the following model:

Communications

Using the new communications model, each client application will generate an instance of a CruiseServerClient. Actually they generate a CruiseServerClientBase instance, but the class that implements this abstract class for the new framework is CruiseServerClient. This class does not actually send any messages – instead it translates the method calls (e.g. ForceBuild) into messages (e.g. ProjectRequest), sends the message and then processes the response.

The actual sending is done by an instance of IServerConnection. This instance takes the specified messages and pushes them over the specified channel (either .NET Remoting or HTTP). Because the actual channel is encapsulated by an IServerConnection, it is easy to replace the channel with a different one.

For encrypted communications I added a new channel called EncryptingConnection. This channel is then inserted between the client and the underlying communications channel:

EncryptedCommunications

This means that the messages are encrypted (both ways), but the underlying transports (e.g. HTTP or .NET Remoting) can still be used without any changes.

There are a couple of extra changes. First, the original request message gets replaced by an EncryptedRequest message. This contains the original message, but encrypted (of course), and the original action that was requested. Secondly, the action has been changed to ProcessSecureRequest – more on this when I cover the server side changes.

EncryptingConnection is also responsible for the hand-shaking required to set up the encrypted communications. When a message is sent, the connection checks to see if it has a password. If it does not have a password, sets up a new common password by the following process:

  1. Ask the server for its public key
  2. Generate a new secret (using RijndaelManaged)
  3. Encrypt the secret using the server’s public key (using RSACryptoServiceProvider)
  4. Send the secret to the server and wait for the response
  5. Store the secret locally

Once this has been done, all messages are then encrypted using the common secret (again with RijndaelManaged). This includes both request and response messages.

The actual sending of the messages is then done by passing the message onto the underlying channel.

Server Communications

Now that the client can send messages, we need to look at the server side. After all, if the server can’t understand the messages, then nothing will be done!

All communications into the server come in via CruiseServerClient. This is a MarshalByRefObject-derived class that uses .NET Remoting. All HTTP communications actually go via the dashboard, which passes them onto the server using .NET Remoting. So this model simplifies things – I only need to change CruiseServerClient!

Currently CruiseServerClient has one overloaded method for processing messages – ProcessRequest(). This takes the incoming message, works out which method to call, converts the message into the required objects (if required) and then calls the method. It also handles generating the response and adding any error information.

To handle secure messages I have added a ProcessSecureRequest (). This method is called by ProcessRequest() and acts as a middle-man. Basically, when ProcessRequest() gets a secure message, it passes it onto ProcessSecureRequest(), which then works out which methods to call, converts the message, etc.

I have also added three other new methods:

  • RetrievePublicKey() – this will send the server’s public key to the client. If the server does not have a public/private key pair it will generate the pair (using RSACryptoServiceProvider).
  • InitialiseSecureConnection() – this receives the common secret from the client, decrypts it and stores it locally.
  • TerminateSecureConnection() – this will remove the common secret for a client from the local store.

These methods are called as part of the hand-shaking between the client and the server.

Additionally, as part of these changes, I have added a new property to the messages called ChannelInformation. This property has information on how the message was transported – i.e. metadata about the message itself.

Currently, there is only one implementation – RemotingChannelSecurityInformation. This says the messages was transported using .NET Remoting. On this class is a property called IsEncrypted. ProcessRequest() generates an instance of this class and sets IsEncrypted to false, while ProcessSecureRequest() generates an instance with IsEncrypted set to true.

Turning On Encryption

Encryption is turned on from the client-side. When a client wants to communicate with a server using encrypted communications, they need to set UseEncryption to true in ClientStartUpSettings.

Currently, this is not possible with the dashboard, but I have added it to CCTray. When a new server connection is added (for either .NET Remoting or via the dashboard), there is a new option of turning on encryption:

CCTray Encryption

To use encrypted communications, all that is needed is to check this box.

Unfortunately, due to the way CCTray is configured, it is not possible to turn on encryption for an existing server. Instead the server needs to be removed and re-added (yuck!) This is probably a good area for tidying up in a future release of CCTray.

Enforcing Encryption

All this work so far has been to set up encrypted communications. At this point, it is up to the client to decide whether the channel is encrypted or not – the server doesn’t really care. We need some way of telling the server to only accept encrypted communications (i.e. to enforce encryption).

To do this, I have added a new configuration option to the server security settings – channel. This is an optional setting and has one required property – the type of channel. The following shows how to configure a channel to use encrypted messages:

  1: <internalSecurity>
  2:   <channel type="encryptedChannel"/>
  3:   <users>
  4:     <!-- Omitted for brevity-->
  5:   </users>
  6:   <permissions>
  7:     <!-- Omitted for brevity-->
  8:   </permissions>
  9: </internalSecurity>

This tells the security manager it will only accept communications over an encrypted channel.

When a message is received by the message processer (i.e. after it has been received by CruiseServerClient, processed and passed on), it calls a method called ValidateRequest(). This does some simple validation checks (the message is less than a day old and it hasn’t been duplicated). I have expanded this validation check to detect a channel definition and if present to validate it.

The Basics Of Encryption

This provides some of the basic pieces for encrypted communications. It certainly is not a comprehensive solution – there are still some areas uncovered (like validating the server is who it says it is).

In terms of where this can go, there are the following items that can be included:

  • Additional encryption mechanisms (e.g. DES, triple DES, AES, etc.)
  • Additional security channels (e.g. SSL, negotiated)
  • Validation of the server (perhaps via X.509 certificates)
  • Use encryption from the dashboard

But this provides a start. Let me know what you think so far.

Posted in CruiseControl.Net, Security | Tagged: , , , | Leave a Comment »

One More Piece of the Puzzle

Posted by Craig Sutherland on 9 July, 2009

Security is Not Quite Finished…

Way back when I started on security for CruiseControl.NET, I wrote about a number of different areas that needed to be covered. Since then, I have completed most of them. Most, but not all…

One area that I originally wrote about was “man in the middle” attacks. To understand this attack, we need to step back first and look at the parts of CruiseControl.NET. CruiseControl.NET can be divided into two general parts: the server and a client.

The server is the heart of CruiseControl.NET, it performs the builds, checks the source control repository, etc. The client is a remote connection to the server, that a user can interact with – which can be either CCTray or the web dashboard. The client generally communicates with the server over a network:

Client-Server

Now, unless both the server and the client are on the same machine, this opens the possibility of a “man in the middle” attack. Generally, we assume that the message goes from the server to the client or vice-versa over the network without anything in between. But, this does not have to be the case. Instead, a third party can position itself in between:

Min-in-the-Middle

In this scenario, all messages go through the third party, allowing potential malicious use of the system. Alternately, the third party could just monitor the traffic, such as with a network sniffer:

Sniffer

Either way, it is now possible for a third party to see and interact with the messages that are passed. As the messages could contain sensitive information (e.g. passwords and login credentials) or can control the server (e.g. start/stop projects, force/abort builds, etc.), we don’t particularly want a third party in between!

Now, people might say this is not an issue for them, but unless you can guarantee a secure network (or both the client and server are on the same machine), you are vulnerable to this type of scenario.

What Can be Done?

Before I look at what can be done, let’s look at why this attack can happen. When either the server or the client wants to communicate, they generate a message to send. This message is plain old text (well, actually XML, but close enough). This means there are open messages flying around the network:

Messages-Plain

Anyone can look at these messages and/or change them, and neither the client or the server would be any wiser. Actually, this isn’t just an issue with CruiseControl.NET, this is an issue with any communications over a network, like any HTTP traffic over the Internet. Any pages that are browsed via http:// are sent plain text. This is where https:// comes in – it secures the messages that are passed. The question is, how is this done?

The answer is very secure – each and every message is encrypted:

Messages-Secure

Since the messages are no longer plain text, any third party in the middle cannot read or modify them. A nice simple solution to the problem. But, like anything, things are never quite that easy!

In order for each side to understand the messages, there needs to be a common understanding – messages are using this form of encryption with this password. Now, with https:// the browsers handle this for you automatically (or almost automatically), so there is no need for user interaction. However, for CruiseControl.NET, nothing like this exists, so it will be my task to build it.

Reaching an Agreement

Now I’m not a cryptographer, so this post will simplify things (a lot!) But here is my basic plan of attack. For encryption there are two basic types – symmetric and asymmetric.

Symmetric is where both sides share a common secret (e.g. a password) and they both use this secret for encryption and decryption. Asymmetric is where there are two secrets – one is used for encryption and the other for decryption. A message encrypted with one secret cannot be decrypted with the same secret – it needs the matching secret to be decrypted.

This means one secret can be common knowledge – typically called a public key. Anyone can encrypt some data using the public key, and nobody can read that data unless they have the other secret – commonly called the private key. In our case, the server will have a public/private key pair. Any client can request the public key and use it to encrypt data to send to the server.

However, this plan has two problems. First, this only works for sending data to the server. Since anyone can access the public key, they could decrypt any data being sent back to the client. This can be resolved by giving the clients public/private key pairs as well, but now the server has a lot more work tracking which public key is needed for which client! The second problem with with asymmetric encryption in general – it is a more expensive (and hence slow) operation to perform than symmetric encryption.

There is a common solution to these two issues – combine the two types of encryption. When a client first connects to the server, it requests the server’s public key. Since this is public knowledge, there is no security hole. The client then generates a secret, encrypts it with the public key and passes it back to the server:

Handshaking

Since the password is encrypted with the public key, only the server with its private key can decrypt it – again no security hole. All subsequent communications between the server and the client then use symmetric encryption with the common secret – a much less expensive form of encryption. The server still needs to keep track of all the password, but it means the client doesn’t need both a public and a private key, so there’s a bit of a gain.

How Is This Done?

That’s the basic theory of things – you now know I’m going to implement encryption on the messages to secure them. This will prevent a third party from either reading or modifying any messages. This will use a public/private key pair on the server to set up a common secret between the two, with all subsequent communications using symmetric encryption.

The basic process will be something like this:

  1. Client requests public key from server
  2. Server sends public key
  3. Client generates secret, encrypts it with the public key and sends it to the server
  4. Server sends a confirmation
  5. Client and server then exchange messages with symmetric encryption

Nice and simple. But there are some catches:

  1. Not everyone will want to use this
  2. Someone can still pretend to be the server
  3. Needs to be extendable

Catch #1 can be set at both the server and the client sides, with the server having the ultimate say. If the server does not return a public key, then steps 2-4 will be skipped and the messages will be passed in plain text. The client can also skip straight to step 5 and just pass messages in plain text. However, the server will have a setting to enforce encryption – i.e. if the client attempts to send plain text messages and the server does not like them, they will be rejected!

Not sure on how to handle catch #2 yet – but I imagine this can be done by checking a hash. The server would generate a hash using its private key and the client would then decrypt it using the public key – thus verifying the server is who it says it is. This would require some external way of passing the public key though.

Catch #3 is fairly straight-forward – I will expand the server security configuration to include this. Each encryption method will be configurable – and people can add their own if they wish.

Anyway, that’s enough for tonight. I’ve got my general plan, in my next post I’ll go into details on how this will be implemented.

Stay tuned…

Posted in CruiseControl.Net, Security | Tagged: , | 3 Comments »

Working Towards a Vision

Posted by Craig Sutherland on 25 May, 2009

What Was Past

One of the changes that I recently added to CruiseControl.NET (for the 1.5 release) is a common communications library. This project is a cut-down version of Remote – I stripped out everything that had nothing to do with communications (e.g. exceptions, NetReflector, lots of interfaces, etc.)

The aim for this library is simple – it contains everything that is needed for a client to communicate with a server. This includes all communications protocols – currently HTTP and .NET Remoting – plus an implementation of every possible method. Additionally it contains a number of classes to simplify the process of communicating with a server.

Considering a lot of this already existed within Remote, you might ask why I have added another library to do this? The answer is simple – Remote contained the basic components for communications, it didn’t actual provide anything to facilitate the process. Instead, each client had to write its own mechanisms for communications – which is why CCTray has one way for communications, the dashboard has another and the server uses yet another way (when it needs to communicate with other servers.) Making a change in one wouldn’t affect the other – so if there was a common change it needed to be made to all three!

Finally, these mechanisms were deeply entrenched within each client. I couldn’t just take the communications part of CCTray and use it – I had to include everything else (and CCTrayLib has a lot of stuff in it!) I certainly tried and did produce a simple command-line client that used CCTrayLib. The problem was it needed all the other dependencies for CCTray, and it wasn’t the easiest thing to use.

What Is Now

As I wrote above, I have added a new communications only project to CruiseControl.NET. Remote still contains everything, plus the new communications work, while the communications library only contains the communications classes (hence it is a subset of remote.)

The heart of this library is a class called CruiseServerClientBase. This class is actually an abstract class, but it exposes all of the communications methods. The actual implementations of this class take the methods and pass them onto the server for processing. This means a developer does not need to worry about how the methods are transmitted, just that they are transmitted.

Since CruiseServerClientBase is an abstract class there is a static factory class called CruiseServerClientFactory that generates instances of it. This can be as simple as just saying “I want a client class” or as complex as saying “I want a HTTP client class that communicates to the localhost server”. Eventually over time this factory will handle a whole variety of communications protocols – while hiding the complexity from the developer.

The following shows the only line that is needed to instantiate a CruiseServerClientBase:

var client = CruiseServerClientFactory.GenerateClient("tcp://localhost:21234");

This will create a client for connecting to the server on localhost. Since the protocol is tcp:// it will create a .NET remoting client. There are also methods to create HTTP or .NET Remoting clients directly – GenerateRemotingClient() and GenerateHttpClient().

Under the hood these methods all create an instance of CruiseServerClient. This is another facade class that provides common functionality. With the 1.5 release CruiseControl.NET is moving to a message-style method interface. This style means every message has a request message and a response message. CruiseServerClient generates the request messages, passes them onto a IServerConnection instance and then processes the response. The IServerConnection instance is actually responsible for transmitting the messages.

As you can guess, there are HTTP and .NET Remoting implementations of IServerConnection. These serialise the message, send it using the correct protocol and then deserialise the response. This response is then returned from the implementation.

As such, it is possible to completely bypass CruiseServerClientFactory and CruiseServerClient and use the IServerConnection instance directly. However this would mean you’d need to write the code to generate the messages yourself, and you’d need to process the responses yourself. CruiseServerClient does all of this plumbing for you.

The following shows how it is possible to trigger a force build with just two lines of code:

var client = CruiseServerClientFactory.GenerateRemotingClient("tcp://localhost:21234");
client.ForceBuild("A project");

As an added bonus, it is very easy to change from .NET Remoting to HTTP, you’d just change the address. The communications library hides all the underlying complexity for you.

However, before I say everything is roses, there is one current limitation: this will only work with the new 1.5 version server. There is no backwards compatibility.

Which brings me to…

What Is Coming

This work all started out of the security work I did for CruiseControl.NET. I got frustrated by the number of places that needed changing, and the number of different ways, so I merged and simplified them. This opened up some ways of making things simpler under the hood.

However there is still the question of previous versions of CruiseControl.NET. The new library will only work with 1.5 or later versions of CruiseControl.NET servers. It would also be nice to allow backwards compatibility. Now this is much more challenging as a number of base classes have been changed to work with messaging, but I still think it is a worthwhile goal.

I should also mention that HTTP compatibility is broken between 1.4.4 and 1.5. Since CCTray promises that HTTP can be used between versions, I am aiming to ensure that at least HTTP compatibility is ok, and then if possible .NET Remoting. That is the reason why there is a CruiseServerClientBase base class, with only one implementation. These older versions do not use the messaging style method calls, and so won’t be able to use CruiseServerClient. Instead they will need to make their own implementations.

Another step for current functionality is to convert CCTray, the dashboard and the server to all use the new client. These currently still have their existing ways of doing things (although I have started converting CCTray). This means in future, we will only need to change one place to change all three clients! Now that is exciting news to me :-)

And finally I can write about what I think is really exciting – a CruiseControl.NET SDK.

One of the great points about CruiseControl.NET is its flexibility. It has a lot of functionality in-built, plus a lot of ways of configuring this functionality. And if that is not enough, people can write their own extensions. But that’s where the good news stops – there isn’t exactly a lot of documentation on how to write extensions, how to configure them or how to use them. Plus just to complicate things, the code of CruiseControl.NET isn’t very well documented.

For the communications library I’m going to build up an SDK. This will include:

  • The library itself (the API)
  • A help document (both compiled and HTML)
  • Examples (both code and help-based)
  • Quick starts (processes to get someone up and running)

The idea behind this is to provide a knowledge base for a person new to CruiseControl.NET (although no new to programming) and help them to quickly build applications for CruiseControl.NET.

So as you can see, I have a vision that I’m aiming for with the new Communications library. Over time I’ll try and write up some more posts about this library. This library – together with the server extensions – opens up a whole world of possibilities for expanding CruiseControl.NET.

Stay tuned…

Posted in CruiseControl.Net, Tools | Tagged: | Leave a Comment »

Simplifying Communications, Part 2

Posted by Craig Sutherland on 25 February, 2009

The Story Continues, Again…

In my last post (here) I modified the server in preparation for building a communications client. This involved adding a new method to handle “generic” messages. This method took in an action name and a request message, and then returns a response.

Now it’s time to build on this and start putting together a communications client.

New vs. Old

The first question is where will the communications code go? At the moment there are two choices – Remote or a new project.

Remote is currently the communications library within CruiseControl.Net, but it also handles a number of other items (e.g. exceptions, events, interfaces, etc.) Additionally it depends on the NetReflector library.

Adding a new project would mean potential duplication, although it would be smaller!

In the end I decided to add a new project in the same folder and link to the existing files. The new project has the same namespace (although a different assembly name). Additionally I modified a couple of files to include compiler directives (#if…#endif) to exclude the NetReflector classes – this removes the dependency on NetReflector.

Now I can use the same classes, but without all the extra baggage. Additionally I can include the new communications classes in Remote later on if I think they are necessary for the main server.

The Design

First off, I want a generic interface to the communications. This will be a single class that handles all communications calls – this way the application does not need to know whether it is HTTP, .NET Remoting or something else.

Secondly, there will be a number of “transport” channels. Each one of these channels contains the actual communications details (e.g. HTTP, .NET Remoting, etc). When the application wants a new client, it instantiates the channel, start a new client and links the two together.

Finally, to simplify the initial set-up, there will be a factory class to do the above step – plus handle some extra steps (auto-detection of the protocol, etc.)

The following diagram shows the various components:

Communications Client

Implementation

The code consists of five classes and one interface. These are:

  • IServerConnection
  • RemotingConnection
  • HttpConnection
  • CruiseServerClient
  • CommunicationsException
  • CruiseServerClientFactory

Most of these should be straight-forward :-)

IServerConnection

IServerConnection defines the channel to the client. It has one method – SendMessage() and one property – ServerName. ServerName is the name of the server that the connection is for. This is used to set the Server property on the request (since this required for web connections). SendMessage() does the actual sending of the message. The input arguments are the action and a ServerRequest, and it returns a Response.

This is all it does, it doesn’t need to perform any validation of the response, as this will be handled by the client.

RemotingConnection and HttpConnection

These are two implementations of IServerConnection – one for .Net Remoting and the other for HTTP. They handle connecting to the server, converting the messages into wire formats and then converting back again.

RemotingConnection is very simple – the only fancy logic in it is generating the URI for the remote server (and even so, is still very simple).

HttpConnection does a bit more work as it converts the request message to XML and then has to convert the response from XML. Internally it uses a WebClient instance, and just calls UploadValues() to send the data (this is a POST request).

CruiseServerClient

This is the biggest of the classes. Each available action on the server has a matching method here. CruiseServerClient takes the incoming arguments and puts them into a request message (of the correct type). This message then gets passed onto the IServerConnection instance, which sends it to the server and returns a response.

When the response is returned CruiseServerClient validates the response. If the response has a status of failed, it will throw an exception (see CommunicationsException below), otherwise it will return the data items (if any).

This class has similar helper methods to what was added to CruiseManager – GetServerRequest(), GetProjectRequest() and ValidateResponse() – to help with this processing.

It also allows the calling application to set a target server. If a target server is not set, then the server name from the server connection is used. Otherwise the target name is used. This is required for HTTP calls where the target server and the connection server can be different.

CommunicationsException

A CommunicationsException is thrown whenever the remote server returns a failure response. This encapsulates the errors and makes it easier for the calling application to differentiate between errors from the remote server and errors on the client side.

CruiseServerClientFactory

The final class is CruiseServerClientFactory. This provides helper methods for starting a new client. Currently there are helper methods for starting a .NET Remoting connection, an HTTP connection and a generic connection.

The generic connection will attempt to detect the connection type from the URI. If the URI starts with http://, then an HTTP connection is started. If the URI starts with tcp:// then a .NET Remoting connection is started. Anything else throws an exception.

This class can be bypassed and the calling application can start its own IServerConnection and wire it to a CruiseServerClient. But this class will help reduce coding in most situations.

An Example

Now that I’ve built the library, now is it used?

First, add the assembly ThoughtWorks.CruiseControl.Communications to the calling project. Just remember that the namespace for this library is actually ThoughtWorks.CruiseControl.Remote – not Communications.

Then instantiate a client. The following shows a few different approaches:

// Generate an HTTP client that targets another server
CruiseServerClient client = CruiseServerClientFactory
 .GenerateHttpClient("http://buildserver/ccnet", "actualserver");
// Generate a .NET remoting client explicity
CruiseServerClient client = CruiseServerClientFactory
 .GenerateRemotingClient("buildserver");
// Generate a .NET remoting client implicity (by auto-detection)
CruiseServerClient client = CruiseServerClientFactory
 .GenerateClient("tcp://buildserver:21234");

To then call the server is as simple as the following:

client.ForceBuild("ProjectName");

And that’s it. Any errors will be raised as exceptions, so make sure there is a try-catch block somewhere around the code.

Where To From Here?

What I have done so far is the basic version of the communications client, which covers most of what the current code can do. Now it’s time to start expanding it to cover other scenarios, e.g. security, handling proxies, other communications channels, etc.

Also, I haven’t covered it in this post, but I have updated my CCCmd (command-line remote client) interface, so next step is to document it and include it in the main code base. I’ll also look at CCTray, the dashboard and the triggers and publishers that connect to other servers.

Another area is to make custom versions of this library for different platforms – e.g. Silverlight, Compact framework, etc. However for Silverlight it needs an asynchronous model, and I haven’t figured out what is the best way to do that yet.

Finally, I’m toying with the idea of making the communications library backwards compatible (e.g able to connect to 1.4.3 servers or earlier). Unfortunately this will require a lot more work as the older versions don’t have the generic message handler :-( So this one might go in the too hard basket.

Posted in CruiseControl.Net | Tagged: , | Leave a Comment »