Automated Coder

Exploring the Code of CruiseControl.Net

Archive for December, 2008

Viewing the Audit Log, Part I

Posted by Craig Sutherland on 26 December, 2008

The Value of Auditing

One of the components I added to the security work was an audit logger component. This allows the auditing of security events, but the other half of the picture is missing – how does someone view the audit log?

Therefore at the moment the audit logging only of use if the person has access to the log location (e.g. the server, etc.) While this does have some value, it would be more useful if the log could be viewed remotely – hence the topic of this post.

A Cunning Plan

As always, I have a plan of attack on how I want to do this. Since the data will need to come from the server, there will need to be changes to three projects: Remote, Core and WebDashboard.

For Core I will add a new security interface to allow reading the audit log. There will only be one reader per security manager (there can be multiple loggers) to reduce any confusion as to where the logs are coming from (and also to reduce the need for duplicate filtering). The reader will take in the starting location and the number of records to read. It also optionally allow a filter, so the user can reduce the number of records.

When this component is finished I will then add a new plug-in to the dashboard to display the retrieved audit records. This will display the records in a table – plus when the user clicks on a record it will display a pop-up with additional details.

Nice and simple? Hopefully :) But because there is a fair amount of work involved I’m going to split this task over two posts. In this post I’ll cover the server-side changes, and in the next post the dashboard plug-in.

A Record of Events

The first part of the process is to add a class to pass the audit information around. This class is called AuditRecord and contains the following properties:

  • Time: The time the event was logged
  • Project: The name of the project the event is for
  • User: The name user the event is for
  • SecurityRight: The outcome of the security action (e.g. Allow or Deny)
  • EventType: The type of security event (maps to SecurityEvent)
  • Message: Any additional audit data

This class is part of the Remote project and has been marked as serialisable so it can be passed over remoting.

Some Fluid Filters

For the filters I wanted to use some fluid syntax – this will make it easier for building the actual filters in future. The syntax I have in mind is:

filter = AuditFilters.ByProject("Project #1").DyDateRange(DateTime.Today.AddMonths(-1), DateTime.Today);

This will generate a filter that contains all projects with the name “Project #1” that occurred in the past month.

To accomplish this I added a new interface called IAuditFilter and a static class called AuditFilters.

The main method on the interface is called CheckRecord(). This checks a record against the filter and if it matches returns true, otherwise false. Each filter must implement this method.

Additionally there are a number of methods to enable the fluid syntax:

  • ByProject()
  • ByUser()
  • BySecurityRight()
  • ByEventType()
  • ByDateRange()

Each of these methods returns a filter that performs the specified filter. To reduce the amount of duplicate code each of these methods is implemented by a class called AuditFilerBase. As long as the filter inherits from this class the fluid methods methods are automatically included.

AuditFilters also has the same fluid methods, plus another method called Combine(). This joins two or more filters together and returns the combination. This filter is an OR operation – it will return all records that match any of the child filters.

Finally I added an implementation of each filter. These are straight-forward – they are called the type of filter suffixed with “Filter”. They just perform the required check and that’s it. Each filter has two constructors – one that takes in the filter criteria and a second that has the criteria and an inner filter. The inner filter is used for chaining filters (performing an AND operation).

Finishing the Puzzle

The final piece of the puzzle is the actual reader itself. This is a new interface called IAuditReader. As far as the end-user is aware, everything is still done through CruiseServer (and CruiseManager, etc.) To achieve this CruiseServer and ISecurityManager both have a new method called ReadAuditRecords() that take in the required parameters and call the required security component to get the records. The CruiseServer implementation also requires a session token as this method is secured (it requires the ViewSecurity permission).

But in the end the actual task of reading the records get passed to the IAuditReader that has been configured. At the moment, since there is only one logger, I have added only one reader – FileXmlReader.

This turned out to be a little bit tricky. While the data is written in an XML format, it violates the rules of XML because there are multiple root elements. In the end I modified FileXmlLogger so each record is on a single line (removed new lines and added one at the end of each record). Then the reader loads the entire file in one go and splits it into the lines.

To actually read the lines the method starts at the last line and works its way through the lines until it comes to the starting line (i.e. the record number specified by the user). I had to do it this way because there can be blank lines (due to the way I did the splitting), but it works!

Once the method has found the starting line it then starts parsing each record and adding them to the result set. If the there is a filter then this gets checked before the record is added. Once the result set has the specified number of records in it the process stops.

The actual parsing of the record is done on a line-by-line basis. Each line is loaded into an XmlDocument and the relevant pieces of information extracted.

Part I Completed

This completes the first part of displaying the audit log. I can now retrieve all the previous audit records and return them to a client, with paging and auditing (I haven’t worried about sorting).

My next post will carry on this work and display the results in a dashboard plug-in.

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

Validating Configuration

Posted by Craig Sutherland on 24 December, 2008

It’s Alive!

As we continue to work on CruiseControl.Net and add all sorts of useful functionality, the configuration for the server continue to grow and expand. While this offers the end-user more options and flexibility, it also makes things more confusing – especially to the newbie.

In the old days of projects and tasks everything was assumed to be self-containing, with the only references being back to the project. Starting with queues, and now especially with security, there are references to different locations within the configuration. As an example, the queue configuration at the server level defines how a queue works, but unless the queue is referenced by a project it will be ignored. Same with security, it can define references to users, but if the users don’t exist the security is worthless.

To try and help resolve this will take a number of different approaches – documentation, configuration tools and validation.

In this post I’l take a look at extending the configuration validation.

The Current State of Validation

Currently there is some validation within the configuration. The configuration is loaded via Exortech.NetReflector, which performs some validation. I say some because this validation is mainly concerned with type validity (e.g. has the correct data type been set) and expected properties (e.g. is the data there). This is controlled via attributes on the configuration classes in the code. It does not provide any “internal validation”.

Before I continue, what is “internal validation”? I define it as ensuring that all the internal components of the configuration are in place and match. In contrast “external validation” is checking against external resources (e.g. a remote server) to make sure the references are correct.

Previously I had added some code (see my post here) that would validate that a queue definition is actually used. This simply checks for that queue definition is referenced by a project somewhere.

Extending the Validation

While this provided a start, there are so many other areas that can value from this type of validation. But, my previous approach would rapidly result in a huge validation section within NetReflectorConfigurationReader. What I need is a simpler, more component-based method of validation.

To achieve this I have added a new interface called IConfigurationValidation. This contains a single method called Validate() that takes in an instance of IConfiguration. The idea is each class that needs internal validation implements this interface. NetReflectorConfigurationReader then checks for the existance of this interface and if defined it calls it. Thus NetReflectorConfigurationReader no longer needs to know the validation rules.

As a proof of concept I moved the queue validation rules into DefaultQueueConfiguration and implemented the interface. Now the validation for each queue definition is performed within the queue itself.

I also implemented the interface for Project. Project contains a large number of other classes – ITasks, ISourceControl, ILabeller, etc. So while it does not contain any internal validation of its own yet, it needs to check all these child items to see if they are valid (assuming they implement IConfigurationValidation.)

Validating Security

With this framework in place I am now ready to validate the security. There are two checks I’m going to currently implement:

  • Security is defined at the server level when it is included in a project
  • The assertion references point to valid objects

The first check was done by modifying Validate() in Project. If the project security is defined (e.g. not NullProjectAuthorisation) then check that the server level is defined (e.g. not NullSecurityManager). Otherwise the configuration is incorrect and throw an exception.

The second check was a bit harder, but I did this in the end by modifying DefaultProjectAuthorisation and AssertionBase to both implement validation. DefaultProjectAuthorisation merely iterates through each assertion and validates each one. AssertionBase checks to see if it is a reference assertion, if so it checks to see if the reference is defined.

Moving On

While I had originally approached this exercise as a security validation task, I’ve built a framework that can allow for any item to be validated. The next step would be to see if any other tasks or components need internal validation and add it in.

But I’ll leave that to someone else ;-)

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

Introducing Security Tutorials

Posted by Craig Sutherland on 23 December, 2008

Where To Begin?

The changes I have made recently to add security to CruiseControl.Net allows a lot of flexiblity and control. However, with this flexibility also comes increased complexity – making it harder for someone to understand what is required and why, let alone actually configuring the security.

To try and make things easier, I’m thinking of writing a series of posts on different ways to configure the security. These will all be based on the current implementation of security, and so might change over time. But I will test them and and add to add them into the test suite.

So, if you have any scenarios then let me know and I’ll look at doing some tutorials on them. So far the ideas that I have are:

  • Small development team, high level of trust, most projects are open to all
  • Large development team, high need for security, requirement for auditing and accountability
  • Open source project, multiple developers, few administrators
  • Contracting firm, large number of projects that need to be secured

Each scenario will cover from planning to implementation, including both the server and client-components (e.g. CCTray and Web Dashboard).

I’m planning on covering them as step-by-step processes – this is what I would do and why. It will also be a good place to discuss some of the current limitations.

I’ll also fully test them, and hopefully I’ll be able to put together an automated process for this. In the long term these will also serve as test-scenarios going forward (e.g. for future work around security).

So let me know if there is anything you would like me to cover :-)

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

Securing the Security

Posted by Craig Sutherland on 22 December, 2008

Preamble

Last week I was asked to add a plug-in to the dashboard that would show the security configuration. This gave me a couple of ideas of additional plug-ins to add, which I have now partially implemented. However, this now raises another issue – anybody can now see the security configuration. So, to get around this I want to add another security permission to only allow some people access to the security plug-ins.

Locking Down the Server

Before I can do this, there is another issue to be covered first. The permissions model I have currently added only works for projects – it does not handle server-level permissions.

To handle this I have added an assertions element to the security manager configuration. This is where people can define assertions that are for the server-level (e.g. user and role definitions). I also added a new method called CheckServerPermission() which checks against these assertions. Now there is a mechanism in place for checking server-level permissions.

The next step is to modify CheckSecurity() in CruiseServer. If a empty project name (string.Empty or null) is received, then it assumes that it is a server-level check and thus calls the new CheckServerPermission() method. Otherwise the standard project-level checking is performed. (I also modified the log messages to be more relevant.)

Now that I can check permissions at the server-level, the next step is to add a new permission.

A Permission to View

The new permission is called ViewSecurity. I have added it to the SecurityPermission enum, plus modified AssertionBase base to include it. This involved added a new property, plus backing field, and then modifying CheckPermissionActual() to return the new permission.

The next step is to lock down the relevant methods in CruiseServer. The three methods that require this permission are:

  • GetSecurityConfiguration()
  • ListAllUsers()
  • DiagnoseSecurityPermissions()

This involved modifying the method signatures to take in a session token (plus all the interfaces and pass-through classes), and then making a call to CheckSecurity() – passing in string.Empty for the project name.

The final step was to modify the plug-ins so they first retrieve the session token, and then pass it on.

Security Secured

With all this completed the security plug-ins are now locked down. In order to view any of these plug-ins the user must either have the ViewSecurity permission, or belong to a role that does.

Task completed :)

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

Hey! Where’s My Session Gone?

Posted by Craig Sutherland on 22 December, 2008

A Small Problem…

Yesterday I was playing around with the security branch of CruiseControl.Net, adding a bit more functionality, when I ran into a small problem. As this is the second time this problem has affected me (in slightly different variation), I thought it’s time to write a post on the issue.

First, in order to understand how this problem works let’s take a look at a page in the web dashboard:

Page Components
Page Components

At a very high level the page can be broken into page content and the site template. The content is what is generated by the plug-in, whereas the site template is added to the page via one of the many decorators (yes, it is also broken into components, but that’s another post :) )

My problem was all the URLs in the site template contained the correct session token but the URLs in the page content contained an older (and expired) session token! This means the session tokens were coming from two different locations.

Building a URL

When I added the security I didn’t want each and every plug-in builder to have to know about security. Instead it should be totally transparent to any component builders (unless they need to use it).

To achieve this I used a class called ICruiseUrlBuilder - which is one of the family of classes that builds the URL (read more about it here). The basic purpose of these classes is to generate an output URL that can be used in the pages.

Hence I extended these classes to also add in the session token. This way the individual plug-ins just call the URL builder and the session token gets magically added.

Now this works because all the class instances are generated on the fly and added to objection so they can be used by any other classes. So every page request I generate the new session token adding and retrieving classes, hook them up to the URL builders and then forget about them.

The Problem

Without going into the headache I had finding the problem, here is the cause:

The site template decorator instance is always generated and added to objection for each page request. Hence the session tokens are always the latest (i.e. associated with the page request).

The page content comes from a plug-in, which can use NetReflector to retrieve the configuration (this is not the only approach, but it is the most common). The configuration is loaded once, when the web application starts, and is then cached. Every subsequent web request retrieves the cached configuration.

Now because some plug-ins need a URL builder they have it as a constructor argument, so objection automatically adds it. So, the first time the plug-in is served, it gets a URL builder with a link to the correct session token. The next time, the plug-in is not reloaded – it is retrieved from the cache, which contains the URL builder from when the page was created. The problem is this URL builder links to all the page variables (e.g. the session token) from the original page request!!!

At this point I haven’t decided whether this is an issue with the design of the application, my mis-understanding of the application, or somewhere in between, but still yuck :(

Note: Actually, when URLs are static the design does make perfect sense, it’s just security needs dynamic URLs which change for each request. So I’ve started doing things which weren’t in the original design.

A Solution

To get around this problem I changed where the URL builder comes from. I’ve added a new property to ICruiseRequest which contains a URL builder.Then instead of retrieving the URL builder in the constructor, I use the one from the request. This way, each and every request will contain its own URL builder, which links to the correct session token.

At the moment I’ve only done this for the security plug-ins, but someone will need to look at the other plug-ins to see if this problem also exists!

Take-home Message

So, to reiterate the main point I learnt:

Plug-ins are cached, as are all the parameters set using their constructor! Never use a constructor parameter for request-specific values (e.g. session tokens).

Hopefully this will save someone some heachaches in the future when developing plug-ins.

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

Diagnosing Permissions

Posted by Craig Sutherland on 20 December, 2008

Why Can’t I…?

The larger and more complex a security setup becomes the greater the likelihood is that something won’t work! Hopefully this is an issue with the configuration, rather than the code, but either way it would be nice to narrow down where the problem is occuring.

To try and help with diagnosing permissions issues I have added a new plug-in to the dashboard that will allow an administration to diagnose what is happening.

The Design

The new plug-in will be similar to the security configuration plug-in. It will work into two modes – server or project. However, instead of displaying the configuration information will display a list of all the users that have been defined.

Clicking on a user in the server mode will display just the user name (using a JavaScript pop-up via AJAX). Clicking on a user in the project mode will display the permissions that user has (again using JavaScript and AJAX).

I did initially think about adding some diagnostics as to how the permission is generated, but this turned out to be a bit more complex (on the server side). Therefore I won’t be including it in the initial version.

Server Modifications

Like my previous plug-in, this one also requires changes to the server-side as well. CruiseServer (and CruiseManager, ICruiseServer, etc.) will need to return two types of data:

  • A list of all the users
  • A set of permissions for a user

To simply things the list of users will actually come from ISecurityManager and CruiseServer will just act as a pass-through layer (yes, yet another one!) So, time to start implementing.

First I added a new method to ISecurityManager and its implementation, SessionSecurityManager, called ListAllUsers(). This method iterates through all the security settings and generates a set of UserNameCredentials whenever it finds an IAuthentication. These credentials contains the user name, the display name and a friendly authentication-type name. These then get added to a list for return.

To enable the names I also made a couple of changes to IAuthentication. I added UserName, DisplayName and AuthenticationName properties to the interface. Most of the implementations already had UserName and DisplayName, but AuthenticationName is new. This just returns a friendly-name describing the type of authentication (and so will generally be hard-coded).

The set of permissions needs to come from CruiseServer, as ISecurityManager doesn’t know anything about projects.This is a new method called DiagnoseSecurityPermissions() – which will return the permissions for a user and one or more projects (I’m trying to build in some flexibility for some future ideas).

I added a new class to Remote called SecurityCheckDiagnostics which will contain the results of the check. This has the name of the permission, user and project, plus whether the permission is allowed or not (not worrying about inherit here). This gets returned from DiagnoseSecurityPermissions() in a List<> instances and can be serialised (and thus passed via remoting).

The actual generation of this list is very simple, just iterate through all the projects and check each permission with a modified version of CheckSecurity(). To retrieve the list of possible permissions I used Enum.GetValues() on SecurityPermission. Each result is added to an instance of SecurityCheckDiagnostics, which is then added to the list.

I needed to use a modified version of CheckSecurity(), called DiagnosePermission(), because the normal version performs logging and raises errors on failures (which would slow performance). The modified version just checks that everything is there and then performs the security check (via the CheckPermission() method on IProjectAuthorisation).

That was a lot of work for a couple of simple tasks, but now it’s all done, including unit tests.

Displaying the Users

Now it’s time for the fun part – actually generating the output. Since this will look similar to the configuration plug-in, I’ll just take the same approach and copy the existing code and then modify it. This gave me a new class called ServerUserListServerPlugin, with all the occurances of security configuration replaced with user list, and a second class called ServerUserListProjectPlugin for the project-level plug-in.

This of course looks the same as the configuration plug-in, just with a different name and entry point. So, the next step is to copy the template and start to modify it, then generate the data to be displayed. The new template contains a table with user name, display name and authentication name. To populate the table I first needed to call the new ListAllUsers() method and store it in the velocity context. Then I just used the values in generating the table – nice and simple.

That now gives me the following output:

User Display List
User Display List

Which looks the same for all the projects as well. Now it’s time to do the fun part – pop-ups!

A Little jQuery, a Dash of Ajax and Viola – Dynamic Displays

Since I’m adding some client-side functionality, the first question was how to do it. Now-a-days there is a whole raft of options – from page refreshes to flash/silverlight. Rather than complicate things I decided to use Javascript, together with one of the framework libraries (to simplify my work). Again there is a range of options, but I choose jQuery in the end simply because it is being supported by Microsoft.

So, first I downloaded jQuery core (from http://docs.jquery.com/Downloading_jQuery), then I built a custom version of jQuery.UI that contained the dialog widget and some of the helper widgets (from http://ui.jquery.com/download_builder/). Finally I went to ThemeRoller (http://ui.jquery.com/themeroller) and generated a theme for the dialog. And with that I’m already to add some dynamic functionality.

The actual pop-up itself was simple – I just added a <div> element to the template and used jQuery to build a dialog from it. Then I added an onclick event handler to each row wihich displays the dialog (via calling javascript). The only thing remaining is to call the permissions diagnostics via AJAX and I’m done.

The actual AJAX call was simple – just another jQuery call and this automatically sent a HTTP post off to the server and loaded the response into the <div>.

But then I ran into a problem!

The current actions all get decorated with a SiteTemplateActionDecorator - thus wrapping the results of each action in the site template. For what I’m doing, I just wanted an HTML fragment – and nowhere can I add this :(

Sending Naked Content

After thinking about a few different ways I settled on adding a new interface called INoSiteTemplateAction. When the object initialiser comes across an action that also uses this interface it generates a different set of decorations – this time without the site template. This might not be the nicest way of doing it, but at least it ensures that all the other decorations are correctly added. From here I generated an implementation of this interface that just inherits from ImmutableNamedAction.

With this framework in place, I’m now ready to generate an AJAX response. I added a new ImmutableNamedActionWithoutSiteTemplate to NamedActions on my plug-in. This just points back to the plug-in. When Execute() is called on the plug-in it checks to see whether a user name has been set in the form values, if so it generates the user diagnostics, otherwise the user list.

The following shows the end-result of these changes:

Permission Diagnostics
Permission Diagnostics

So, this new plug-in will list all the users on a server. When the user clicks on a user it will bring up details on that user. If the user is viewing it within a project context, then the permissions for that project are displayed. All done without refreshing the page :)

I’ll look at checking in the code tomorrow, and then start work on the audit log viewer plug-in.

Enjoy…

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

Exposing Security

Posted by Craig Sutherland on 18 December, 2008

Return to Security

After a bit of a hiatus on the security front it is time to return. I have received some feedback from one of the other devs on the CruiseControl.Net project, and he has made a couple of suggestions (thanks Ruben).

The first suggestion is to add some dashboard plug-ins to expose the security information – which is what this post will start on. The second is on the documentation, which I will cover in a future post.

Some Security Plug-ins

Most of my focus on security has been around securing the server and then allowing the clients to authenticate (and from there to authorise and be audited). However, I haven’t exposed the security details anywhere – which can make it harder to configure and diagnose security issues.

Ruben has suggested I add some plug-ins to the web dashboard which will help with this. After some discusions we decided on three plug-ins that would be useful:

  • Configuration display plug-in – similar to the project configuration display
  • User permissions plug-in – this will display the users and which permissions they have
  • Audit log display plug-in – to allow an administrator to see what people have been doing

Each of these plug-ins will require a bit of work, so I’ll cover each in a seperate post. In this post I’ll take a look at the first plug-in – exposing the configuration.

The Design

My design has been inspired by a couple of the other plug-ins. First there is the “Project Configuration” in the project-level sidebar. This plug-in retrieves the configuration from the remote server and displays it as plain old XML. This allows a user to quickly see how the project is configured and it doesn’t require any special processing.

The second plug-in that provided inspiration was “View Server Log” in both the server-level and project-level sidebars. This plug-in (which is actually two) displays the server log at both the server level and at an individual project level. When it displays it shows a list of the projects across the top and the individual log information underneath. It can be accessed via either the project or the server sidebars – and based on the entry point it will automatically display the right context.

Based on these two plug-ins my new plug-in will display the configuration XML, with entry points from both the project and server sidebars, plus the list of projects across the top. I’d also like to go one step better than the project configuration display and use syntax highlighting to make it easier to use (plain old black and white doesn’t do it for me!)

Retrieving the Configuration

Before I can display anything the first step is to actually retrieve the security configuration. This will need to come from the remote server, so it needs a change to ServerAggregatingCruiseManagerWrapper, CruiseManager and CruiseServer (plus their associated interfaces). CruiseServer is the initial source of the information, the other two classes are pass-through classes to get the information to where is it needed (i.e. the plug-in).

So, I added a new method to ICruiseServer and CruiseServer called GetSecurityConfiguration(). This will return all the security configuration on the server as an XML string. Since the configuration already uses Exortech.NetReflector this wasn’t too hard, I just needed to add a couple of wrapper classes.

Since I’m wanting to include all the configuration – which is defined in two places, the server and the individual projects – I added a wrapper class called ServerSecurityConfigurationInformation. This contains the top-level server configuration, plus the security configuration for each project. It uses NetReflector to generate the XML (and thus uses the NetReflector attributes itself). I also added a post-processing step to hide all the passwords. This is simplily an extra step to load the XML into an XmlDocument and use an XPath search to find all elements called “password”. The text of these elements are replaced with asterisks.

The second wrapper class is called ProjectSecurityConfigurationInformation. This wraps the project configuration, plus includes the name of the project (so the plug-in knows which configuration is for which project). These are then stored in an List<> instance within ServerSecurityConfigurationInformation, so only one class needs to be reflected.

All CruiseServer does is generate a new instance of ServerSecurityConfigurationInformation, adds the top-level security and then iterates through all the projects and adds their security. If a project doesn’t have security then no entry is added. Finally it calls the ToString() method on ServerSecurityConfigurationInformation to get the plain old XML and returns it.

Displaying the Configuration

Since I’m basing my display on the server log plug-in I just copied all the code from ServerLogServerPlugin (which is the class that implements it) and modified it slightly. This involved changing the reflector type, action name and link description. I then modified the fetch call to get the security configuration rather than the log and that was the basic version.

The next change was to implement the project-specific display. For the server log it calls different methods on CruiseServer, but I just had the one method. So this involved loading the XML into an XmlDocument and using XPath to select the correct elements. Now I could see the configuration for the different areas.

My next change was to add a new NVelocity template to provide the custom titles, and use the new template instead of the server log template. Nearly there!

The final stage is to add some nice formatting. After a quick search on the web I found CSharpFormat (http://www.manoli.net/csharpformat/) – which does everything I wanted, and a lot more! He kindly provides the code free-of-charge, providing we keep his blurb in the code (I just compiled the code as-is and included the library). So the final step is to format the code using this utility and display it. All done :)

The Results

I’ve added this plug-in to Subversion, and included the plug-in in the configuration by default (people can remove it if they don’t want it).

As for how it looks, here are a couple of screen shots:

Security Configuration - Server Level
Security Configuration – Server Level
Security Configuration - Project Level
Security Configuration – Project Level

Hopefully these views will make it easier for people to use security.

In my next post I’ll look at building a permissions checker – again web-based. This will make it easier to validate the security settings (hopefully!)

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

HTTP and Tray Icons

Posted by Craig Sutherland on 13 December, 2008

Continuing with the Prototype

I’ve been slowly adding my functionality to my CCTray replacement prototype. It’s slowly approaching the stage where I think it will be ready for people to try playing with it, but it’s not quite there yet. In this post, I cover a couple more areas of functionality, so some quick refactoring and discover an issue (resource conflict?)

HTTP Transport

The original CCTray offers two possible transports – .Net Remoting and HTTP (I have added a modification to allow it to handle any number, but it hasn’t made it into the trunk yet). In contrast my new replacement doesn’t have any transports – they need to be added as server monitors (thus allowing any number of possibilities). Currently I’ve already built a .Net Remoting implementation, now it’s time to implement HTTP.

.Net Remoting was very simple – just needed to instantiate a remoting instance of ICruiseManager and then call the relevant methods. Sure I needed to do some translations between their objects and mine, but still very simple.

HTTP is a bit more complicated – everything needs to be converted into HTTP requests and the responses are just plain text (well, actually XML, but close enough). Therefore there’s a lot more work!

But the good news is it has already been done – in the original CCTray application :) So all I did was copy and paste, and then make a couple of modifications for my application.

So, since I’m making this a modular application I started a new project for the monitor, added the basic classes (the IServerMonitor implementation, plus some configuration settings). Then I copied the following classes/interfaces from the original:

  • IDashboardXmlParser
  • DashboardXmlParser
  • IWebRetriever
  • WebRetriever

These classes I copied over unchanged. I also copied over code from HttpCruiseProjectManager and HttpCruiseServerManager into my IServerMonitor implement and then modified them to work with my code.

I did discover one oversight along the way – the dashboard needs the server as well as the project. But this information is not stored anywhere! Instead it is assumed that the server is part of the web URL (I say assumed because this is not always the case!) Thus the HTTP transport needs to parse the URL, retrieve the server name and then pass it in the web request. This would probably be a good area to tidy up in a future patch (but it will need to be at the server side, not the client side).

Otherwise the HTTP transport is now finished :-)

Some Refactoring

In IServerMonitor the calls to ForceBuild(), AbortBuild(), StartProject() and StopProject() all took in a string for the project name. When I discovered the above issue I changed this to take in a ProjectDetails instance.

Initially I made the change with the hope of extracting the server name from the full details, but I discovered that the name isn’t passed down from the server. Instead I now use it for getting the web URL. Since I modified the interface I also needed to modify the .Net Remoting instance, but this was a simple matter of changing it to use the name from the instance.

In the future when the server side is modified to pass the server name (or alias) then this can be used as the information will already be in place.

General Settings

In the configuration window I had added a tab for general settings. This currently has two settings, show in tray and hide when minimised, which currently do nothing.

So I added a NotifyIcon instance to the main window, with an icon and application name, and added some code to show/hide this based on the configuration settings. I also added an event handler to the SizeChanged event – this detects when the window is minimised and if necessary hides the window (very straight-forward stuff).

To the NotifyIcon instance I added a ContentMenuStrip which has a show and an exit command. The exit command just calls Exit() on the controller (thus shutting down the application). If the window is hidden, then the show command restores it to it’s previous state, otherwise it brings the window to the front of the z-order.

An Issue?

While I was adding the general settings I also discovered an issue where one of the monitor processes was crashing. I think this was due to a conflict in writing to the log file, so I added a retry loop (in a try/catch block) with a 10ms delay. After this change the error went away, but it could possibly recur some point – especially if there are lots of server monitors!

My resolution? Currently none :( I don’t know enough about multi-threading and cross-process resource locks. So this will need to a topic for me to research later (unless somebody else know how to do it and can tell me.)

Enough for Now

That’s enough changes for now. I had hoped to work on security, but the HTTP changes took a bit more work than planned (yes, even though I copied the other code). But for my next post I’m planning on covering security (once I’ve thought about it some more).

Stay tuned…

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

Listening In

Posted by Craig Sutherland on 11 December, 2008

Informing the User

One of the key elements of the new prototype is something called an event listener. An event listener is a separate class that implements IStatusListener, that is instantiated within a server monitor and does just that – listens for events. When it hears an event that it is interested in, then it can do whatever it likes!

This is important because in the current CCTray, this type of functionality was hard-coded into the application. Even if the user doesn’t want speech or X10, the functionality is still there (yes, they can disable it, but they can’t remove it). In contrast, event listeners can sit in their own libraries and so are independant of the main application.

There are two parts to an event listener, first I need to develop the event listener and add it to the bin folder. Second the listener needs to be configured. In the long term a developer will only need to worry about the first point, but since I’m still working on the prototype I need to do both parts :(

How To Listen

The first part is building an actual listener. I’m going to build a listener that adds a little pop-up window, similar to the MSN notification window. Therefore I’m going to call my event listener PopUpNotification (yeah, not very original!)

The only interface that I need to implement is IStatusListener – this has two methods: Register() and Unregister(). Register() is called when the server monitor starts up and it allows the event listeners to add handlers to any of the events (ServerChanged, QueueChanged, ProjectChanged – I’ll add some more later). Unregister() is called when the server monitor is stopping and it allows the event listener to gracefully remove any handlers.

For my pop-up notification I am only interested when a project changes, so I added an event handler for the ProjectChanged event.

Next, I built a small pop-up window that has an icon, the name of the project and a message:

When a ProjectChanged event is received I display this window, and populate the project name and status. I added a method to the window to do this automatically (including a pop-up effect). And that’s all there is to it.

Configuring the Listener

Configuring the listener should just be an easy process of the user selecting the listener and then setting any configuration options, so my task is to make it that easy.

On the project configuration tab there is a button labelled “Event Listeners”. All I need to do is wire up some functionality. So, the first thing to do is add a new form, called ListenersWindow:

Event Listener Configuration
Event Listener Configuration

This window displays the name of the server monitor (just so the user can always see where they are) and a list of event listeners. To add a listener to the monitor the user checks the event listener.

Since event listeners can have additional configuration settings there is a nice empty pane next to the list. When the user selects a checked listener it will check to see if there are any configuration options for the listener. If there are no options then it will tell the user, otherwise it will show a PropertyGrid with the options in it:

Event Listener Configuration with Custom Configuration
Event Listener Configuration with Custom Configuration

These settings come from an IConfigurable instance – if the event listener implements this interface then it has configuration options.

The code behind this form is very simple – it just lists all the possible event listeners it can find, then it goes through the list and instantiates each instance that is already in the configuration. When the user selects an event listener it checks to see if it has configuration and if so displays it, otherwise it displays a message saying there is no configuration. When the user clicks on “Save” it goes through and generates a list of PluginConfiguration instances that contains the type name and any custom configuration.

What’s in a Name

One item I didn’t mention earlier is the name of the plug-in. The full type name is something like ThoughtWorks.Leo.PopUpNotification.EventListener,…, but in the screenshots above it has the name “Pop-up Notifications”.

This is handled by adding a custom attribute to the class called PlugInName. This allows a developer to associate a friendly-name with any classes that appear in lists (e.g. event listeners, transport protocols and display tabs). When the application loads the classes for these lists it checks to see if this attribute exists, if so then the friendly-name is displayed, otherwise the full type name is displayed.

Another Item Down

That’s yet another item on my to-do list completed. Next I’m planning on doing some tidying up, which will include an HTTP transport protocol, some general settings and maybe even security.

Stay tuned…

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

Selecting Projects, Server Names and Exclusion Switching

Posted by Craig Sutherland on 8 December, 2008

Return to the Brave New CCTray

I’ve finally managed to make some time to return to my CCTray replacement prototype (I’ve had a busy month just past).

One of the areas that I had left undone was the configuration – especially the selection of which projects to display. Currently the display will show all projects for a server – whether or not people want to see them. In this post I look at adding project selection to the configuration.

I’ve also had a couple of other ideas, so I decided to add them in. First I thought it would be nice to give the server a “friendly” name, so I’ve added this in. And secondly it would be nice to change how projects are added to the display list.

Selecting Projects

In order to allow the user to select a list of projects, I first needed to show a list of projects. Now this involved a bit of work as I needed to get the list of projects from the server. Since the new prototype doesn’t directly connect to any servers, this needed to be done via IServerMonitor. So, my first step was to add a new method called ListProjects(). This will connect to the remote server, list all the projects and return them in a List<ProjectDetails>. After this everything was easy.

Firs, in the project configuration I instantiated an instance of the new IServerMonitor (this was after the connection properties had been validated.) Then using this new instance I retrieved the projects list and passed it onto a new window called ProjectSelectionWindow:

Selecting Projects
Selecting Projects

This has a ListView to display the projects, a couple of buttons and a label telling the user which server the list has come from. The input parameters include the list of projects, the currently selected projects and the server name – these are all self-explanatory for how they are used.

When the user clicks on “Save” this raises an event, which is monitored by the configuration window. All this does is stored the list of selected projects into the configuration.

Showing Projects

Configuration was the first half, the second half was to modify the project display. To reduce the number of comms messages I implemented the project selection at the IServerMonitor level. This means the monitor is responsible for filtering which projects get sent on.

This was a simple matter of adding a check everytime a project was changed. If the project was on the allowed list the event was raised, otherwise nothing happens.

With this simple change there was no need to modify the main window, instead it just displays everything it receives.

More Server Configuration

As I stated in the introduction, I have decided to add two more configuration options:

New Configuration Options
New Configuration Options

I have added a display name for the server. This will display a “friendly” name for the server, instead of the server address. If this name is omitted then the address will still be displayed. As well as modifying the configuration I also had to modify the main window to display the new name.

Second I have added a check box allowing the user to “Exclude Projects by Default”. The default setting is new projects on a server will automatically be included in the projects list – instead the user chooses which projects to exclude. This check box allows this to be swapped so it works the same way as the current CCTray (projects must be selected in order to be displayed.) Again, the actual selection was implemented at the IServerMonitor level.

What Next?

I’ve almost finished the server configuration now (at least my current plan of configuration), the only outstanding item is to configure event listeners. So for my next post, it’ll be time to bit the bullet and finally implement event listeners.

Stay tuned…

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