Automated Coder

Exploring the Code of CruiseControl.Net

Posts Tagged ‘Tutorials’

FastForward.NET: An Initial Setup

Posted by Craig Sutherland on 6 August, 2009

Introduction

When FastForward.NET Monitor is initially installed, it will be in a “blank slate” state. There will be no servers configured, no templates or plug-ins loaded, etc. Basically, it will be pretty useless.

The first task in making the Monitor useful is to configure it. This tutorial will go through the steps necessary to configure the Monitor to display the projects for a server, plus show tray notifications of changes.

Initial State

The following is a screen shot of the initial state of the Monitor when it is first run:

Initial-1

There are no projects listed in the “All Projects” tab, and the Monitor Explorer tree is also empty. I haven’t shown it, but the other tabs are also empty.

To change this, go to File –> Settings:

Initial-1a

This will open the settings dialog. The first tab (Servers) shows all the configured servers, plus has options for manipulating these servers:

Initial-2

The second tab (Settings) shows the general settings for the Monitor:

Initial-3

The third tab (Templates) shows the loaded templates. These templates are used in the build history for generating different reports. As well as displaying the templates, this tab allows us to add and remove templates:

Initial-4

The final tab (Plug-ins) shows the loaded plug-ins, plus allows us to add, remove and configure the plug-ins:

Initial-5

As you can see, the initial state of the Monitor is pretty empty – no servers, templates or plug-ins have been configured! Let’s go through the process of adding a plug-in and a server.

Displaying Build Notifications

In its default state, the Monitor does not display any notifications. In order to display notifications, we need to add a plug-in that displays notifications.

We want to add system tray notifications. This will add a little icon to the system tray (normally in the bottom-right corner of Windows). When a build starts or finishes it will pop up a balloon notification.

This is done in the Plug-ins tab. Click on the “Add Plug-in” button. This will display the add plug-in dialog:

Initial-6a

Clicking on the drop down list will display all the available plug-ins:

Initial-6

Since we want to add system tray notifications, we will select this plug-in. This then brings up a description of the plug-in:

Initial-6b

Clicking on “Ok” will then load the plug-in to the list of loaded plug-ins:

Initial-5a

Note, this will not actually “load” the plug-in into the Monitor. This occurs when the “Ok” button is clicked on the settings dialog. This will close the dialog and update the monitor with any changes.

Most plug-ins offer additional configuration options. These can be accessed by selecting the plug-in and then clicking on the “Configure Plugin” button. This then opens a configuration dialog for that plug-in. For example, this is what system tray notifications shows:

Initial-6c

And that’s it for adding and configuring plug-ins. The application takes care of everything else for us.

Adding and Configuring a Server

Since the entire purpose of the monitor is to watch one or more CruiseControl.NET servers, let look at what is required to add and configure a server.

In this example, I will add a server using .NET Remoting as the transport. This will be a simple 1.5.0 instance of CruiseControl.NET.

The starting point for this example is the Servers tab of the settings dialog. Click on the “Add Server” button. This will display the Add Server dialog:

Initial-7a 

This gives a number of basic connection settings. The first field, Address, is the address of the target server. This is generally a URI (e.g. tcp://somewhere, http://somewhere/ccnet, etc.) but it can also just be a server name. If it is just a server name, it will assume that it is using tcp:// as the protocol.

Transport allows the user to select which transport to use:

Initial-7b

The (Default) option will use the protocol in the address to determine the transport mechanism used. Use this drop down if you need to specify a different transport from the address protocol.

The Connection to pre-1.5.0 server check box allows connection to an older style CruiseControl.NET server. In theory this will use .NET Remoting, but there are no guarantees. I would only use this option together with HTTP.

The final option is Target Server. This is used for connecting to a remote server that in turn connects to multiple CruiseControl.NET servers (e.g. the dashboard). At the moment this is an experimental feature in the underlying Communications Client, so I’m not sure how well it works.

Once all the settings have been added, click on the Ok button. This will then attempt to validate the server:

Initial-7

Monitor will attempt to connect to the remote server and retrieve its version number (if possible). If this process works, then the server configuration is valid, otherwise the details you entered were incorrect.

If this works, the Server Configuration dialog will appear:

 Initial-8

This is the same dialog that is displayed when the “Configure Server” button is clicked in the Servers tab. This allows the user to configure additional settings for a server (it is not possible to change the transport settings for a server).

The display name is a name that will be used locally within the Monitor. If this name is omitted, then the address of the server will be used instead.

The polling interval is how often the remote server will be checked.

Use Encryption is to use encrypted communications with the remote server. This is only applicable for 1.5.0 or later servers.

Finally, the New Projects option configures how the monitor will handle new projects on a server. There are two options: always show or always hide. When always show is selected, the projects will be automatically displayed in the monitor – otherwise they will not appear.

The final configuration option for a server is which projects to display. In the server configuration the user can set how projects are generally handled. To show/hide specific projects the user needs to select the projects. This is done by clicking on the “Projects” button on the Projects tab. This will list all the available projects for the server:

Initial-9

Any projects that have a check box next to them will be displayed, all other projects will be hidden.

Remember, to actually save and apply these settings, the “Ok” button in the settings dialog must be clicked.

End of Tutorial

And that’s it for configuring plug-ins and servers. The result of this tutorial is there will be projects displayed in the monitor:

Initial-10

Additionally, there will be an icon in the system tray that shows build notifications.

In my next tutorial, I will go over the information displayed in the monitor, plus show some more plug-ins. Stay tuned…

Posted in FastForward.NET | Tagged: , | 2 Comments »

Improved NCover Integration

Posted by Craig Sutherland on 29 May, 2009

Is Your Code Covered?

One of the important metrics for TDD is code coverage – how much of the code base is actually being tested by unit tests. It’s not the only metric (even with 100% coverage you can’t guarantee that everything will be perfect), but it is a reasonably easy metric to measure.

There are various tools out there to measure this, but one of my favourites is NCover. NCover originally started as an open source tool, and has now moved into the commercial realm. I originally didn’t see the point in measuring code coverage, but since I’ve been using NCover at work, I now realise it is invaluable. And I certainly think they’ve improved things a lot with NCover 3.

If you want to find out more about NCover, they have a website with all the details – http://www.ncover.com/. They have even put together a pretty good tutorial on integrating CruiseControl.NET with NCover – http://docs.ncover.com/how-to/continuous-integration/cruisecontrol-net/.

However, the integration between the two products isn’t really that good. I should stress, it’s not because of NCover – they do everything right – it’s because CruiseControl.NET has a way of working, and we’ve so far forced everyone into using that path.

But the good news is this is changing!

The Current State

Currently CruiseControl.NET doesn’t directly handle running NCover – it has to be run from the <exec> task, or as part of a build script (e.g. <nant>, <msbuild>, etc.) Next, the results from NCover need a second task to merge them – otherwise they are ignored!

Finally, CruiseControl.NET uses XSL-T files to convert the results (which must be in XML) into HTML. So, if there is a huge amount of data, the result displays are very, very slow.

So, there are a number of hoops to jump through for getting NCover results into CruiseControl.NET. A much better approach would be some simple tasks to directly integrate and display the results – including NCover’s HTML reports.

And What’s New

As an alternate approach to using <exec> or build scripts, I have added two new tasks to CruiseControl.NET. These tasks allow CruiseControl.NET to run NCover directly and automatically merge the results!

Why two tasks? This is because of the way NCover works – there is a profiling application and a reporting application. Originally I disagreed with this approach, but since I’ve played around with it, I’ve come to agree with this approach. With the two applications, you can profile a project once and then generate multiple different reports. And if you have a huge suite of tests, it’s certainly good news to run the profiler only once!

Before I move into a tutorial on these tasks, I should mention that these tasks are designed to run with NCover 3.0. The profiling task might work with NCover 2.0, but I certainly haven’t tested it (nor will I), and the reporting task certainly won’t!

A Quick Tutorial

So, how do you run NCover from CruiseControl.NET?

First, you need to make sure NCover is installed and your code is built. Additionally you’ll need to know the location of both NCover and the unit test runner executables, and also the location of the binaries. Once you know this this, then you’re all ready to start!

Running NCover

Now, open ccnet.config (the default location of this is in the server folder in the install location). If you’ve already used CruiseControl.NET, you should have one or more projects set up – otherwise take a look at the documentation on how to do this (http://confluence.public.thoughtworks.org/display/CCNET/Configuring+the+Server). So you should have something that looks like this:

<project name="MyProject">
    <webURL>http://mybuildserver/ccnet/</webURL>
    <workingDirectory>C:\Integration\MyProject\WorkingDirectory</workingDirectory>
    <artifactDirectory>C:\Integration\MyProject\Artifacts</artifactDirectory>
    <!-- <triggers /> -->
    <!-- <sourcecontrol /> -->
    <tasks>
        <!-- Build task here, e.g. <nant>, <msbuild>, etc. -->
        <!-- other tasks here ... -->
    </tasks>
    <publishers>
        <xmllogger />
    </publishers>
</project>

To add NCover profiling, add an <ncoverProfile> task to the tasks block. I would recommend adding this after the test binaries have been built so you are profiling the latest version. As a bare minimum you need to specify the locations of NCover, your test runner and the binaries.

Your project will then look something like the following:

<project name="MyProject">
  <webURL>http://mybuildserver/ccnet/</webURL>
  <workingDirectory>C:\Integration\MyProject\WorkingDirectory</workingDirectory>
  <artifactDirectory>C:\Integration\MyProject\Artifacts</artifactDirectory>
  <!-- <triggers /> -->
  <!-- <sourcecontrol /> -->
  <tasks>
    <!-- Build task here, e.g. <nant>, <msbuild>, etc. -->
    <!-- other tasks here ... -->
    <ncoverProfile>
      <executable>C:\Program Files\NCover\NCover.Console.exe</executable>
      <program>tools\nunit\nunit-console.exe</program>
      <testProject>myproject.test.dll</testProject>
      <workingDir>build\unittests</workingDir>
      <includedAssemblies>myproject.*.dll</includedAssemblies>
    </ncoverProfile>
  </tasks>
  <publishers>
    <xmllogger />
  </publishers>
</project>

This tell CruiseControl.NET to run NCover from C:\Program Files\NCover\NCover.Console.exe. The test runner is nunit-console (this is located in C:\Integration\MyProject\WorkingDirectory\tools\nunit\nunit-console.exe). The project that will be tested is myproject.tests.dll (this could be any valid nunit project).

This will run NCover and automatically merge the results. You could stop at this point and just use the old NCover XSL-T files to display the results.

However, NCover also comes with an impressive suite of reports, which be also be run directly. To do this you need to add one or more <ncoverReport> tasks. Each report task can run one or more reports – this allows you to change the parameters.

For example, to produce a summary report with a minimum coverage of 95%:

<ncoverReport>
  <executable>C:\Program Files\NCover\NCover.Reporting.exe</executable>
  <outputDir>ncover\reports</outputDir>
  <reports>
    <report>Summary</report>
  </reports>
  <minimumThresholds>
    <coverageThreshold metric="SymbolCoverage" value="95"/>
  </minimumThresholds>
</ncoverReport>

Or to generate a full report that is ordered by coverage percentage in a descending order:

<ncoverReport>
  <executable>C:\Program Files\NCover\NCover.Reporting.exe</executable>
  <outputDir>ncover\reports</outputDir>
  <reports>
    <report>FullCoverageReport</report>
  </reports>
  <sortBy>CoveragePercentageDescending</sortBy>
</ncoverReport>

The full details on what can be reported on is available from the NCover site (http://docs.ncover.com/ref/3-0/ncover-reporting/).

Coming back to our example project, I’ve added the default report (full report):

<project name="MyProject">
  <webURL>http://mybuildserver/ccnet/</webURL>
  <workingDirectory>C:\Integration\MyProject\WorkingDirectory</workingDirectory>
  <artifactDirectory>C:\Integration\MyProject\Artifacts</artifactDirectory>
  <!-- <triggers /> -->
  <!-- <sourcecontrol /> -->
  <tasks>
    <!-- Build task here, e.g. <nant>, <msbuild>, etc. -->
    <!-- other tasks here ... -->
    <ncoverProfile>
      <executable>C:\Program Files\NCover\NCover.Console.exe</executable>
      <program>tools\nunit\nunit-console.exe</program>
      <testProject>myproject.tests.dll</testProject>
      <workingDir>build\unittests</workingDir>
      <includedAssemblies>myproject.*.dll</includedAssemblies>
    </ncoverProfile>
    <ncoverReport>
      <executable>C:\Program Files\NCover\NCover.Reporting.exe</executable>
      <outputDir>ncover\reports</outputDir>
    </ncoverReport>
  </tasks>
  <publishers>
    <xmllogger />
  </publishers>
</project>

Again, this will automatically merge the results for you. Additionally the reports are also stored in the ncover/reports folder (this will be in the C:\Integration\MyProject\Artifacts folder).

And that’s all that is required to run NCover in CruiseControl.NET! Nice and easy, but still allowing the full power of NCover.

Displaying Reports

As well as using the XSL-T reports (from the NCover tutorial) you can also directly display the HTML reports within the dashboard.

To display a report within the dashboard is very easy. First open dashboard.config (the default location of this is in the webdashboard folder in the install location). Next find the <buildPlugins> and add an <htmlReportPlugin> element for each report to display.

For example, to display the full coverage report your <buildPlugins> section would look like the following:

<buildPlugins>
  <buildReportBuildPlugin>
    <xslFileNames>
      <xslFile>xsl\header.xsl</xslFile>
      <xslFile>xsl\modifications.xsl</xslFile>
    </xslFileNames>
  </buildReportBuildPlugin>
  <buildLogBuildPlugin />
  <htmlReportPlugin description="NCover Report" actionName="NCoverBuildReport" htmlFileName="ncover\fullcoveragereport.html" />
</buildPlugins>

And that’s all that is required – no need to copy any files! This is what it will look like:

NCover

As you can see, this is the full report from NCover. In this case, the report is actually a frameset with sub-reports! Clicking around within the report works just like expected. Additionally, if you don’t have enough screen space, you can open up the report in its own window (so you don’t have all the CruiseControl.NET stuff around it.)

You can add as many <htmlReportPlugin> elements as desired – just make sure the description and the actionName are different for each.

One Final Note

This new functionality is all part of the 1.5.0 release currently. This means if you are using 1.4.4 or earlier, it won’t work. Since this is still in development, I have included the full reference for the new tasks below. The binaries and installer can be downloaded from http://ccnetlive.thoughtworks.com/CCNet-builds/1.5.0/.

So feel free to try this functionality – if you have ay problems with it, either leave me a comment or post a message on the mailing list.

Task Reference

This is the full reference for the new tasks. Since these tasks map through to the NCover executables I have also included the mappings for the command-line arguments. The full details of these arguments are available at http://docs.ncover.com/ref/3-0/ncover-reporting/command-line.

ncoverProfile

Name Description Type Required Default
program The program to execute and collect coverage statistics from String Yes n/a
testProject The project that contains the tests. If relative, this will be relative to baseDir String No None
programParameters The parameters to pass to the program. String No None
executable The executable to use. String No Ncover.Console
description A description of the task. String No None
timeout The time-out period in seconds. If the task does no finish running in this time it will be terminated. Int No 600
baseDir The base directory to use. All relative parameters will be relative to this parameter. String No Working directory for the project
workingDir The working directory for the executable. If relative, this will be relative to baseDir.

Maps to //w

String No baseDir
publish Whether to publish the results or not. Boolean No True
logFile The location of the NCover log file. If relative, this will be relative to baseDir.

Maps to //l

String No None
logLevel The profiler log level.

Maps to /ll

Enum (Default, None, Normal, Verbose) No Default
projectName The name of the project.

Maps to //p

String No None
coverageFile The location to write the coverage file to. If relative, this will be relative to baseDir.

Maps to //x

String No Coverage.xml
coverageMetric The coverage metric to use.

Maps to //ct

String No None
excludedAttributes The attributes to exclude.

Maps to //ea

String No None
excludedAssemblies The assemblies to exclude.

Maps to //eas

String No None
excludedFiles The files to exclude.

Maps to //ef

String No None
excludedMethods The methods to exclude.

Maps to //em

String No None
excludedTypes The types to exclude.

Maps to //et

String No None
includedAttributes The attributes to include.

Maps to //ia

String No None
includedAssemblies The assemblies to include.

Maps to //ias

String No None
includedFiles The files to include.

Maps to //if

String No None
includedTypes The types to include.

Maps to //it

String No None
disableAutoexclusion Whether to turn off auto-exclusion or not.

Maps to //na

Boolean No False
processModule The module to process.

Maps to //pm

String No None
symbolSearch The symbol search policy to use.

Maps to //ssp

String No None
trendFile The location to write the trend file to. If relative, this will be relative to baseDir.

Maps to //at

String No None
buildId A custom build id to attach.

Maps to //bi

String No The build label
settingsFile A location to read the settings from. If relative, this will be relative to baseDir.

Maps to //cr

String No None
register Temporarily register NCover.

Maps to //reg

Boolean No False
applicationLoadWait The amount of time NCover will wait for the application to start up.

Maps to //wal

Int No None
iis Whether to cover IIS or not.

Maps to //iis

Boolean No False
serviceTimeout The time-out period for covering a service or IIS.

Maps to //st

Int No None
windowsService A Windows service to cover.

Maps to //svc

String No None
ncoverReport

Name Description Type Required Default
executable The executable to use. String No NCover.Reporting
description A description of the task. String No None
timeout The time-out period in seconds. If the task does no finish running in this time it will be terminated. Int No 600
baseDir The base directory to use. All relative parameters will be relative to this parameter. String No Working directory for the project
workingDir The working directory for the executable. If relative, this will be relative to baseDir.

Maps to //w

String No baseDir
coverageFile The location to read the coverage date from. String No Coverage.xml
clearFilters Should the coverage filters be cleared.

Maps to //ccf

Boolean No None
filters The coverage filters to apply.

Maps to //cf

Array of coverageFilter No None
minimumThresholds The minimum coverage thresholds.

Maps to //mc

Array of coverageThreshold No None
minimumCoverage Whether to use minimum coverage or not.

Maps to //mcsc

Boolean No False
xmlReportFilter The type of report filtering to use.

Maps to //rdf

Enum (Default, Assembly, Namespace) No Default
satisfactory The satisfactory coverage thresholds.

Maps to //sct

Array of coverageThreshold No None
numberToReport The maximum number of items to report.

Maps to //sct

Int No -1
trendOutput The file to output the trend information to. If relative, this will be relative to baseDir.

Maps to //at

String No None
trendInput The file to import the trend information from. If relative, this will be relative to baseDir.

Maps to //lt

String No None
buildId A custom build id to attach.

Maps to //bi

String No The build label
hide The elements to hide.

Maps to //hi

String No None
outputDir The directory to output the reports to. If relative, this will be relative to baseDir. String No None
reports The reports to generate.

Maps to //or

Array of Enum (FullCoverageReport, Summary, UncoveredCodeSections, SymbolSourceCode, SymbolSourceCodeClass, SymbolSourceCodeClassMethod, MethodSourceCode, MethodSourceCodeClass, MethodSourceCodeClassMethod, SymbolModule, SymbolModuleNamespace, SymbolModuleNamespaceClass, SymbolModuleNamespaceClassMethod, SymbolCCModuleClassFailedCoverageTop, SymbolCCModuleClassCoverageTop, MethodModuleNamespaceClass, MethodModuleNamespaceClassMethod, MethodCCModuleClassFailedCoverageTop, MethodCCModuleClassCoverageTop) No FullCoverageReport
projectName The project name to use in the reports.

Maps to //p

String No None
sortBy The sort order to use.

Maps to //so

Enum (None, Name, ClassLine, CoveragePercentageAscending, CoveragePercentageDescending, UnvisitedSequencePointsAscending, UnvisitedSequencePointsDescending, VisitCountAscending, VisitCountDescending, FunctionCoverageAscending, FunctionCoverageDescending) No None
uncoveredAmount The amount of uncovered items to report on.

Maps to //tu

Int No None
mergeMode The merge mode to use.

Maps to //mfm

Enum (Default, KeepSourceFilters, Destructive, AppendFilters) No Default
mergeFile The file to store the merged data in. If relative, this will be relative to baseDir.

Maps to //s

String No None
coverageFilter

Name Description Type Required Default
data The pattern to use for matching items, String Yes n/a
type The type of item. Enum (Default, Assembly, Namespace, Class, Method, Document) No Default
regex Whether this is a regex or not. Boolean No False
include Whether to include items or not. Boolean No False
coverageThreshold

Name Description Type Required Default
metric The coverage metric. Enum (SymbolCoverage, BranchCoverage, MethodCoverage, CyclomaticComplexity) Yes n/a
value The minimum coverage value Int No None
type The type of item. Enum (Default, View, Module, Namespace, Class) No None
pattern The matching pattern to use. String No None

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

Public Service Announcement

Posted by Craig Sutherland on 28 January, 2009

Do You Want to Modify CruiseControl.Net?

One of the things about CruiseControl.Net being open source is that things only change if people give of their time to make changes. Currently there’s about four or five of us who make changes to the code (at least based on the check-ins), so sometimes things just don’t happen (or things that people would like don’t happen).

Now there are a number of reasons why people don’t contribute code, but one of them is the complexity of the project (it has grown organically over the past few years). To try and overcome this issue Ruben has started posting a series of tutorials on coding for CruiseControl.Net. You can read these articles on his blog (http://rubenwillems.blogspot.com/).

Additionally if there are other things we could do to make it easier to contribute, please let me know :)

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

Security Scenario 3: Small Open Source

Posted by Craig Sutherland on 23 January, 2009

The Saga Continues…

Previously I’ve put together two scenarios on security. These were:

Both of these scenarios covered in-house development projects. In this scenario I’m going to change tack and look at a small open source project.

Petros has been working on an open source project called Midas for about a year now. This project is hosted on SourceForge, and he is the only administrator. However recently it’s been getting some press and other people have volunteered to help, which he thinks is wonderful!

He has convinced his work (a chemical conversion company) to host a CruiseControl.Net instance for the community to use. However, he doesn’t want to allow everybody full access to the server. He is happy to let everybody view the current status, but he only wants to let approved developers force build. He doesn’t want to let anybody stop or start the projects. Finally he wants to know who performs any release builds.

The Build Setup

Petros’s build setup is really simple – there is only two projects in his config.

The first project is a CI build – it polls every five minutes and performs a build if any changes are detected. This does the standard compile, run unit tests and generate installer. The outputs are stored in a publically accessible location.

The second project is a releasing build. Again it does the compile, unit tests, etc, except this time in release mode. The outputs are then stored on his open source website and a release post is added to tell the world. This project must be manually forced.

The Goals

Since Petros has full access to the server and is the only person who needs access, there will be only one security zone.

This security zone will grant approved developers access to force or abort a build on the project. Currently security does not prevent viewing the reports, so this will not require configuration.

To keep things simple, all force builds will be audited.

The Plan

There will be only one security group – CanBuild. This group will have force build access to both projects, but no other access.

All developers who need force build rights will be manually added to this group.

The Configuration

The full configuration is as follows:

<cruisecontrol>
  <project name="Open_Source(Build)">
    <workingDirectory>C:\Build\OSB</workingDirectory>
    <artifactDirectory>C:\Build\OSB\Deploy</artifactDirectory>
    <webURL>http://localhost/server/local/project/LAS-Main/ViewProjectReport.aspx</webURL>
    <triggers>
      <intervalTrigger buildCondition="IfModificationExists" seconds="300"/>
    </triggers>
    <publishers>
      <xmllogger/>
    </publishers>
  </project>
  <project name="Open_Source(Deploy)">
    <workingDirectory>C:\Build\OSD</workingDirectory>
    <artifactDirectory>C:\Build\OSD\Deploy</artifactDirectory>
    <webURL>http://localhost/server/local/project/LAS-Main/ViewProjectReport.aspx</webURL>
    <triggers>
      <intervalTrigger buildCondition="IfModificationExists" seconds="300"/>
    </triggers>
    <publishers>
      <xmllogger/>
    </publishers>
  </project>
</cruisecontrol>

Again the first step is turning on security – just added the internalSecurity element, plus the users and permissions children.

Adding the Roles and Users

Now the security has been added the next step is to add the users and the CanBuild security group. Since this is an open source project, Petros doesn’t want to bother with much security. Therefore each person who is allowed to build has been added as a password user. At the moment, this is only Petros himself:

<users>
  <passwordUser name="petros" password="whoareyou"/>
</users>

The role is very similar, but just contains the force build permission and the list of users:

<permissions>
  <rolePermission name="all" defaultRight="Deny" forceBuild="Allow">
    <users>
      <userName name="petros"/>
    </users>
  </rolePermission>
</permissions>

I’ve also set the default right on the internal security element to Deny, so everyone else will be unable to do a force build.

Locking Down the Projects

The final step for preventing force builds is to secure the projects. This is the same configuration as previous:

<security type="defaultProjectSecurity">
  <permissions>
    <rolePermission name="all" ref="all"/>
  </permissions>
</security>

Again, this checks that the user is in the role, and if so the user can do a force build. All other permissions are denied at the server level.

Audit Logging

The final step once more is the auditing. Since this is very simple, I’ve just added the default audit logger block:

<audit>
  <xmlFileAudit/>
</audit>

I haven’t added an audit reader as there is no way of accessing it at the moment.

Some Comments

Again, there’s still no way of allowing password users to log onto the dashboard (hence why I haven’t covered it).

One issue I did think about with this scenario is sending the login requests to a remote service (e.g. something like SourceForge or CodePlex). At the moment I don’t know whether these services even have a login API, but if so it would be nice to have a pass-through for this. However since it opens up a whole set of security issues I decided not to even try it!

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

Security Scenario 2: Large Team

Posted by Craig Sutherland on 15 January, 2009

!!Update!!

Since this post security has been modified slightly. Please see this post for further details.

Welcome Back to Security

Here is the second in a set of scenarios on security. In my previous scenario (here) I looked at a small team, this time I’ll look at a large team.

The company Acme Banking, a large multi-national bank. Lu is the manager of the lending application software development department and has a staff of 19 people working for him. He has charged his system admin, Peter, with securing CruiseControl.Net.

Some background, Lu is responsible for three applications: lending applications system (LAS), load approval and tracking system (LATS) and bad debt analysis and recovery system (BARS). Each system is an independent web application with a complex set of business rules and a backing database. To allow interactions between the system each application exposes web services. Finally each application has a number of support tools that are Windows-based.

However, to simplify things, Lu’s department is only responsible for development. The QA department is responsible for all testing (including deployments) and the Server department is responsible for the actual deployment to PROD. All of these deployments are done via hand-overs, with the receiving department responsible for getting the binaries from the build server.

As for department structure, each team has a team leader and a senior developer. There are also between two and six junior developers in each team. Peter is not included in any of the teams as his full-time role is supporting the developers. All staff are on the same network and have windows logins.

Lu wants to limit access for project to the team that is responsible for it. No team is allowed access to any project that belongs to another team. Additionally only the team leader and senior developer are allowed to start/stop the projects, although the junior developers can force builds. Everything done in the system must be audited.

The Build Setup

Each application has two projects – main and tools. Main includes the actual web application, plus the web services, while tools contains all the support tools. This makes a total of six projects.

Each project contains everything required to build the binaries and deploy them to the build server (for the other departments). These are triggered on an interval basis, plus every night at 3am.

Since the hand-over process is manual, there is no impact on other environments. However considering the team size and low-level of trust they want everything locked down.

The Goals

There will be three security zones: low, medium and high. The following table shows these zones:

Zone Description Projects People
Low Permission to force/abort builds. All Junior developers
Medium As above, plus permission to start/stop projects All Team leaders and senior developers
High As above, plus access to security information None Lu & Peter

Each application will be divided into low and medium zones. The high level security zone is generic to the system rather than application-specific.

The Plan

These goals give a total of seven security groups – low and medium for each application plus a high security group. Everybody within the department will belong to one of these seven groups.

This actual model is a little more complex, but I’ve put together a diagram as follows:

Tutorial 2-1

The Configuration

Again I’m going to use the same basic configuration for each project:

<project name=”LAS-Main”>
<workingDirectory>C:\Build\LAS-Main</workingDirectory>
<artifactDirectory>C:\Build\LAS-Main\Deploy</artifactDirectory>
<webURL>http://localhost/server/local/project/LAS-Main/ViewProjectReport.aspx</webURL>
<triggers>
<intervalTrigger buildCondition=”IfModificationExists” seconds=”300″/>
</triggers>
<publishers>
<xmllogger/>
</publishers>
</project>

The project name (i.e. LAS-Main) will be changed for each project – a total of six projects.

Again the first step is turning on security – just added the sessionSecurity element, plus the settings and assertions children.

Adding The Roles and Users

Next, I added the users. Since everyone is on the network I added them with ldapUser elements. This is defined as follows:

<settings>
<ldapUser name=”lu.jones” domain=”localhost”/> <!– Manager –>
<ldapUser name=”peter.smith” domain=”localhost”/> <!– SysAdmin –>
<ldapUser name=”mark.doulos” domain=”localhost”/> <!– LAS Team leader –>
<ldapUser name=”jill.white” domain=”localhost”/> <!– LAS Senior developer –>
<ldapUser name=”john.asher” domain=”localhost”/> <!– LAS Junior developer –>
<!– Remaining users omitted –>
</settings>

Note there is a domain in here – I’ve just changed it to localhost for this example. Without the domain the active directory authentication will fail as the authenticator won’t know where to look.

I’ve also added a server-level assertion for the high-security permissions:

<assertions>
<roleAssertion name=”Admin” defaultRight=”Allow”>
<users>
<userName name=”lu.jones”/>
<userName name=”peter.smith”/>
</users>
</roleAssertion>
</assertions>

This just says that Lu and Peter have full access to everything.

Configuring the Clients

This is exactly the same for scenario one for CCTray. Each individual user will need to go in and configure their security authentication. The only difference is they can use the WinLogin authentication method.

At the moment it is not possible to add the authentication to the dashboard. I’ll look into adding a authentication plug-in and then I’ll update this post.

Locking Down Projects

The final step is to lock down the projects. This is where there is slightly more work than scenario one. Since each project needs to be secured, every project will need to be modified.

There are two ways this can be done. One way would be to add the security to each project, the second is to define roles and then link each project to them. Since there are two projects for each application, with identical permissions I’m going to use the second approach.

In the settings section of sessionSecurity I define each application role. The following shows an example:

<roleAssertion name=”LAS-Developers” forceBuild=”Allow” defaultRight=”Deny”>
<users>
<userName name=”john.asher”/>
<!– Remaining users omitted –>
</users>
</roleAssertion>
<roleAssertion name=”LAS-Admin” forceBuild=”Allow” startProject=”Allow” stopProject=”Allow” defaultRight=”Deny”>
<users>
<userName name=”mark.doulos”/>
<userName name=”jill.white”/>
</users>
</roleAssertion>

This defines the developer and admin (team leader/senior developer) roles for an application. Each of the other applications has a similar definition except with a different list of users.

Then, in each project I add a security section like the following:

<security type=”defaultProjectSecurity” defaultRight=”Deny”>
<assertions>
<roleAssertion name=”LAS-Developers” ref=”LAS-Developers”/>

<roleAssertion name=”LAS-Admin” ref=”LAS-Admin”/>
<roleAssertion name=”Admin” ref=”Admin”/>

</assertions>
</security>

The first two assertions will change to match the application each project is for, while the last one is the same for all projects (gives Peter & Lu access to the projects).

Audit Logging

Finally Lu wants everything audited. This is very simple to do, just add an audit logger and an audit reader. This is done in the sessionSecurity element by adding the following elements:

<audit>
<xmlFileAudit/>
</audit>
<auditReader type=”xmlFileAuditReader”/>

By default these will use an audit log called SecurityAudit.xml in the same directory as the executables. This can be changed by added a location attribute as follows:

<audit>
<xmlFileAudit location=”C:\Logs\CCNet_Audit.xml”/>
</audit>
<auditReader type=”xmlFileAuditReader” location=”C:\Logs\CCNet_Audit.xml”/>

Note that the location must be on both elements and they point to the same location. This is because the two items work independently of each other and it is possible to have multiple audit loggers.

And that’s the security settings for this scenario.

Some Comments

As always, working through this scenario I found a couple of issues.

First, while the LDAP security is generic (i.e. the authentication is handled externally) I still needed to define every user. This is because of the internal validation that happens. As different users would belong to different roles I couldn’t just use a wildcard for the authentication. While this does make things a little more security, it also forces duplication of security :( Instead it would be nice to define something that keys off an LDAP group, hence reducing the need for duplication.

Secondly there is no dashboard plug-in to detect a Windows Login. I haven’t implemented this as I’m not sure of the best way yet (if anybody has any suggestions let me know!) This wouldn’t be so bad, except the only way to view the audit logs currently is via the dashboard!

Complete Configuration

Once again I have posted the complete example on my storage site:

There is no dashboard configuration for the reason above.

Feel free to send me any suggestions for improvements or ideas on how to clarify these scenarios or security in general.

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

Security Scenario 1: Small Team

Posted by Craig Sutherland on 10 January, 2009

!!Update!!

Since this post security has been modified slightly. Please see this post for further details.

Welcome to Security

As I promised previously, here is the first in the set of tutorials on security. In this scenario I’ll look at setting up security for a small, fictitious team.

The company is Acme Insurance, the company that provides development insurance for software houses. Bob leads a team of six people – three developers, a business analyst (BA) and a couple of testers. The systems they develop are in-house systems for the company – and consists of a couple of Windows applications plus an internal intranet web application.

Bob wants to secure their installation of CruiseControl.Net so he knows what is happening and to limit access to certain projects.

The Build Setup

Each application (two windows apps, plus one web app) has three projects in CruiseControl.Net. Additionally there are a few smaller projects for common libraries – which are used by the main applications – bringing the total number of projects to twelve.

Each application, plus the libraries, have a simple compile-and-test build project. This projects ensures that the code builds, the local unit tests run and the successful outputs are copied to a central “store” for the executables. These are triggered on an interval basis (when code is checked in) or via a force build.

The applications also have two deploy projects each – deploy to QA and deploy to PROD. These generate “production” builds, copy all the executables and related files into deployment packages and copy them to the staging area. Additionally the web application is automatically deployed to either the QA or pre-PROD servers. The QA versions run overnight, the PROD versions must be manually triggered.

So despite this being a small team, there are still a fair number of projects, plus some can potentially screw up processes (either QA or PROD).

The Goals

The twelve projects can be divided into three security zones: low, medium and high. The following table helps to define these three zones:

Zone Description Projects People
Low Projects that everybody can access Compile-and-test projects (six) Everybody
Medium Projects that need to limit access Deploy to QA projects (three) Team lead, BA and testers
High Projects that can affect production Deploy to PROD projects (three) Team lead and BA

For low security, they don’t really care what happens to the projects – it is the entire responsibility of the team. While this can still lead to an abuse of trust, the consequences would be reasonably minor.

As the security needs increase, the consequences of someone screwing things up (either deliberately or by accident) increases. Damaging the QA environment could lead to a loss of one or more days work by the testers and the BA – not serious consequences but potentially a large waste of time and resources. Damaging PROD would lead to a serious waste of time, plus potentially damage the company’s client-relationships.

The Plan

With these goals in mind, this gives two actual levels of security. The first level is unsecured – anyone can do anything to the projects and there is no real need to audit anything. This is very similar to how CC.Net currently works.

The security level limits who can access and modify projects in CC.Net. Within this level there are two groups – testers and releasers. Membership to the testers group allows full access to the deploy to QA projects, while the releasers group allows access to all deployment projects.

This definition gives a very simple design – two roles with two users in each. Six projects need security, while the other six do not. Since the users need to be secured they will use passwords (to ensure the other people don’t “use” their user name). Finally, all deployments will be audited to assess the effectiveness of security in the long run.

The following diagram shows how I’m going to implement the security:

Tutorial 1-1

The Configuration

Since I’m looking at the security, not the actual projects, I’m going to use the following general configuration for each project:

<project name=”WinApp1-Build”>
<workingDirectory>C:\Build\WinApp1-Build</workingDirectory>
<artifactDirectory>C:\Build\WinApp1-Build\Deploy</artifactDirectory>
<webURL>http://localhost/server/local/project/WinApp1-Build/ViewProjectReport.aspx</webURL>
<triggers>
<intervalTrigger buildCondition=”IfModificationExists” seconds=”300″/>
</triggers>
<publishers>
<xmllogger/>
</publishers>
</project>

WinApp1 will be changed to the different project names. There are twelve projects in total – their names roughly match the names above (the arrows are changed to dashes). With this background, I can now begin to configure the security.

Turning On Security

First, I’m going to turn on security for the server. This involves adding a security block to the config file. Since there is only one security type defined so far, I’ve added a sessionSecurity element (this can be added anywhere within the config, as long as it is directly under the cruisecontrol element – i.e. it cannot be in a project or queue element). For the moment, I’ll leave it with the default settings.

Running this config through the validator, I see that the security element needs an assertions element and a setting element, so I’ve added some blank instances of these. Now the config file passes validation and security has been turned on for the server. But, all this has done is completely lock down the server, so no one can do anything!

Adding Some Roles and Users

So the next thing to do is to add the users and roles. First, I’ve added the two roles – “Testers” and “Releasers”. These are defined as follows:

<settings>
<roleAssertion name=”Testers” forceBuild=”Allow” defaultRight=”Deny”/>
<roleAssertion name=”Releasers” forceBuild=”Allow” defaultRight=”Deny”/>
</settings>

Each of the roles has force build rights only, all other rights are still denied. Before I can add some people to the roles, I first need to add the users to the security. So I’m going to add four users, each with their own password (which are hard-coded for the moment).

So, now the security settings looks like this:

<settings>
<roleAssertion name=”Testers” forceBuild=”Allow” defaultRight=”Deny”/>
<roleAssertion name=”Releasers” forceBuild=”Allow” defaultRight=”Deny”/>
<passwordUser name=”bob” display=”Bob (Team Lead)” password=”bob1″/>
<passwordUser name=”jane” display=”Jane (BA)” password=”jane2″/>
<passwordUser name=”john” display=”John (QA)” password=”john3″/>
<passwordUser name=”joe” display=”Joe (QA)” password=”joe4″/>
</settings>

Next step is to add the users to the roles, so now the roles look like this:

<roleAssertion name=”Testers” forceBuild=”Allow” defaultRight=”Deny”>
<users>
<userName name=”john”/>
<userName name=”joe”/>
</users>
</roleAssertion>
<roleAssertion name=”Releasers” forceBuild=”Allow” defaultRight=”Deny”>
<users>
<userName name=”bob”/>
<userName name=”jane”/>
</users>
</roleAssertion>

Finally, I added a generic role for all the other uses:

<simpleUser name=”*”/>

This now gives me the roles and users. But, until CCTray and the dashboard are configured, they still can’t do anything!

Configuring the Clients

Configuring CCTray is done on the client-side. The user needs to go to settings, click on the Build Projects tab, and then click on “Add…”. This will open up the list of servers – from here the user clicks on the server to modify and then clicks on “Configure”. This will finally open up the security configuration:

Security Configuration

Here the user will need to check the “Server is secure” checkbox and then choose the authentication mode. Once they have done this they need to click on the “Configure” button and enter their credentials. Finally click on “Ok” all the way back to the main screen and security is now configured for CCTray.

Configuring the dashboard needs to be done at the server level instead. This involves opening dashboard.config and adding the following section underneath <plugins>:

<securityPlugins>
<simpleSecurity/>
</securityPlugins>

This adds a login section to the site, which allows the person to login with their username only. People with password secured accounts will fail to login. For this scenario this mode is fine for most people – the people in the other roles will need to use CCTray.

Now people can login and perform force builds, etc. However, the problem is everyone can force build any project! The next step is to configure the projects.

Locking Down Projects

For the projects that are in the low security zone, there is no need to change the configuration. These will continue to work as-is.

For the remaining projects, I need to lock them down. This is done by adding a <security> element to the project element. At the moment there is only one type of security – defaultProjectSecurity. So to start with I added the following XML to the project element:

<security type=”defaultProjectSecurity” defaultRight=”Deny”/>

The defaultRight attribute is optional, but this changes the default permission so no-one can do anything on it. Of course, this isn’t much use, so it’s time to add in the assertions:

<security type=”defaultProjectSecurity” defaultRight=”Deny”>
<assertions>
<roleAssertion name=”Testers” ref=”Testers”/>
<roleAssertion name=”Releasers” ref=”Releasers”/>
</assertions>
</security>

This is the definition for a medium security zone project, the high security zone is similar, but without the Testers role in it.

And that’s it! Security has now been configured for this scenario.

Some Comments

While this security setup does work, I found a few issues along the way.

First, because the dashboard plug-in only supports one authentication method I couldn’t configure the security plug-ins in the dashboard. Therefore I’ve turned them off in my dashboard configuration for this scenario (otherwise people would be confused).

Second, security is very open by default. While this was intentional, it does mean the onus is placed on the administrator to lock everything down.

Third, passwords are stored openly in the configuration, and people have no way of changing them. This is similar to the basic approach that Subversion uses, but it would be nice to make it a little more secure.

Complete Configuration

For those who want to see my complete configuration, I have added them to my storage site:

Feel free to send me any suggestions for improvements or ideas on how to clarify these scenarios.

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

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 »