Smoke Tester Version 0.03 Released

I have just released version 0.03 of the Post Deployment Smoke Testing Tool. This release focuses on 3 main area.

  • Usability enhancements to the Test Configuration Editor, like linking tests from the editor and the test runner view, sorting tests by execution result and a tool for generating file checksums (MD5, SHA1, SHA256) to make the Checksum tests easier to use.
  • Writing out of Txt, Csv, or XML test reports from the Test Configuration Editor or Command Line Test Runner tool.
  • Added 2 new test types for spawning command line / batch files.
SmokeTester 0.03
SmokeTester 0.03

The 2 new tests for calling command line applications / batch files are useful if you need to test something that the Smoke Tester doesn’t support out of the box. One of the tests (CallExecutableCheckReturnCodeTest) lets you run an executable and check the return code. The other test (CallExecutableCheckOutputTextTest) lets you run an executable and check for the existence of a text string in the console output. These are very useful if you have some separate tools that you use for system checking.

The 3 Laws of Testing

Asimov's IRobot
Asimov’s IRobot

A tester colleague of mine, sent me this little play on Asimov’s 3 Laws of Robotics. They made me smile, so I thought I would share them.

  1. A Tester may not injure a Developer or, through inaction, allow a Developer to come to harm.
  2. A Tester must obey orders given it by BA’s except where such orders would conflict with the First Law.
  3. A Tester must protect its own existence as long as such protection does not conflict with the First or Second Law. 

It’s good to see our testing colleagues have developers backs covered. 😉

Code Example : Quick and Easy Password Generator

As part of my new SafePad 1.3 release, I added a simple tool to help users generate passwords. I looked into many ways of generating secure passwords, but in the end I settled on a technique that was very simple, quick to implement, and produces complex to crack random passwords.

Safepad is commonly used as a password vault for storing passwords for multiple sites in one document. The document is then protected with up to 2 passwords. One feature that was requested was that of generating complex passwords straight into a SafePad document.

The solution I picked is demonstrated below. In SafePad, the maximum password length is restricted to 64 characters.

using System;
using System.Security.Cryptography;

namespace HauntedHouseSoftware.SecureNotePad.Tools
{
    public static class PasswordGenerator
    {
        public static string Generate(int passwordLength, bool singleCase)
        {
            if (passwordLength == 0)
            {
                throw new InvalidOperationException("passwordLength");
            }

            string password;

            using (var randomNumberGenerator = new RNGCryptoServiceProvider())
            {
                var randomNumber = new byte[64];
                randomNumberGenerator.GetBytes(randomNumber);

                password = Convert.ToBase64String(randomNumber);
            }

            password = password.Substring(0, passwordLength);

            if (singleCase)
            {
                password = password.ToLower();
            }

            return password;
        }
    }
}

A coding requirement was to generate passwords that where not repeatable, and to do this I used the RNGCryptoServiceProvider class in .NET. I have already discussed using RNGCryptoServiceProvider in a previous article.

Code Example : Checking Windows Service Status in C#

Sometimes it is useful to be able to check for the existence of a windows service on a local or remote machine and also check the running status of that service. Doing this is very easy in .NET. The following snippets are taken from the windows services tests in the Post Deployment Smoke Tester.

var ctl = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName == "MyService");
if (ctl == null) throw new AssertionException(string.Format("Service with name [{0}] was not found", "MyService"));

The snippet above will check for a named service on the local machine. You can also look for the existence of a service on a remote machine, but supplying the machine name in the call to GetServices, as shown below.

var ctl = ServiceController.GetServices("CENTLPBZBHV1").FirstOrDefault(s => s.ServiceName == "MyService");
if (ctl == null) throw new AssertionException(string.Format("Service with name [{0}] was not found on {1}", "MyService", "CENTLPBZBHV1"));

Scary DDos and Ransom Attack against CodeSpaces

You read pretty much every day about some new virus, or a new attack against a person or company, but last week there was an attack against a company that can only be described as terrifying. The company attacked was Coventry (UK) based Svn hosting company CodeSpaces.

DDos and Ransom Attack against CodeSpaces
DDos and Ransom Attack against CodeSpaces

I read about this attack in The Hacker News. An attacker started a Distributed Denial of Service (DD0s) attack against the company, and also managed to gain access to their Amazon AWS and EC2 dashboard. The attacker then proceeded to hold them to ransom for a large fee to stop the DDos attack. The company, naturally, tried to regain control of their system and started changing passwords. When the attacker realised what they were doing, he started deleting all the companies data from the Amazon cloud servers, including all the backups.

SafePad Version 1.3 Released

Safepad has started becoming quite a popular tool with people, and I get feature requests from users all the time. The 2 most common requests are the following:

  • Caching of session passwords.
  • Generating user passwords to be stored in a secure document.

On this latest release I have focused on these 2 requests.

Caching of Session Passwords

In the previous versions of SafePad, everytime you open a document you have to enter in a password(s). Some users have found this a little painful, because for certain groups of files they use the same master passwords to secure the files, so they felt that when the application is open, they shouldn’t have to re-enter the password each time if the file has the same password.

This has been the most asked for feature request,so I have added it into Version 1.3. As you can see in the screen shot below, when you load a document, there is a check box to ‘Cache Password for Session’ when you check this box, the password(s) will be cached in memory (in encrypted form), so that the next time you open a file with the same password it will just open. If you try to open a file that uses a different password, you will be re-prompted to enter the password.

Passwords Can Now be Cached for a Session.
Passwords Can Now be Cached for a Session.

Once you close the application the cached password will be removed, so it will need re-entering when you load up the application. I didn’t want to get into the problems of saving the encrypted passwords to disk, I would rather just keep them in memory. I hope you find this a big usability feature. I have been using it for over a month (at the time of writing) as I keep all my staff 1 to 1 notes in encrypted files, so it is nice to be able to just open the files in a sessions without entering the password every-time.

Code Example : Pinging a Remote Computer

In this short article I want to show a useful code snippet that allows you to ping a remote computer, much like the command line tool ping.exe. This particular code snippet was taken from a Smoke Test from the Post Deployment Smoke Testing tool that I am the open source moderator for.

Usage of the PingHost method is very straight forward. You just call it and pass in a host name. In the example below that is “www.google.co.uk”, but it could be a server name or ip address.

using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace PingTester
{
    class Program
    {
        static void Main(string[] args)
        {
            string reply = PingHost("www.google.co.uk");
            Console.WriteLine(reply);
        }

        private static string PingHost(string host)
        {
            if (string.IsNullOrEmpty(host))
            {
                throw new ArgumentNullException("host");
            }

            var returnMessage = string.Empty;

            try
            {
                var address = GetIpFromHost(host);
                var pingOptions = new PingOptions(128, true);
                var ping = new Ping();
                var buffer = new byte[32];

                for (var i = 0; i < 4; i++)
                {
                    try
                    {
                        var pingReply = ping.Send(address, 5000, buffer, pingOptions);

                        if (pingReply != null)
                        {
                            switch (pingReply.Status)
                            {
                                case IPStatus.Success:
                                    returnMessage = string.Format("Reply from {0}: bytes={1} time={2}ms TTL={3}",
                                        pingReply.Address, pingReply.Buffer.Length, pingReply.RoundtripTime,
                                        pingReply.Options.Ttl);
                                    break;
                                case IPStatus.TimedOut:
                                    returnMessage = "Connection has timed out...";
                                    break;
                                default:
                                    returnMessage = string.Format("Ping failed: {0}", pingReply.Status);
                                    break;
                            }
                        }
                        else
                            returnMessage = "Connection failed for an unknown reason...";
                    }
                    catch (PingException ex)
                    {
                        returnMessage = string.Format("Connection Error: {0}", ex.Message);
                    }
                    catch (SocketException ex)
                    {
                        returnMessage = string.Format("Connection Error: {0}", ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Connection failed for an unknown reason...");
            }

            return returnMessage;
        }

        private static IPAddress GetIpFromHost(string host)
        {
            var address = Dns.GetHostEntry(host).AddressList[0];
            return address;
        }
    }
}

First of all a call is made to GetIpFromHost, which in turn call the .NET Dns.GetHostEntry method to resolve to an IP address. Then a call is made to Ping.Send(). At this point you will either get a success status or a timeout.  One thing to note though is that some enterprises have Ping disabled using group policy. If this is the case then you will get a “Connection has timed out error.”

High Level Overview of Agile

I have released a course on Pluralsight called Agile Fundamentals that talks about Agile Software Development in detail.

The following video is a really good high level overview of Agile and Scrum. The video is by Ken Schwaber (One of the originators of Scrum). There are lots of Agile and Scrum overviews out there, but this one was particularly good. The video is only 20 minutes long, the sound isn’t great, but the content is spot on.

If you are trying to convince your manager / company / colleagues that Agile is a software development methodology worth following, then this is a good video to show them. The video talks a lot about responding to changes in a market place and how being Agile can help you maintain a competitive advantage.

Post Deployment Smoke Tester Version 0.02 Released

Smoke Test Config Editor
Smoke Test Config Editor

I have released an update to the Post Deployment Smoke Tester Tool. This version mainly includes new test types. The new tests added are:

    • MSMQInstalledTest : This test checks whether the MSMQ messaging service is installed on the server you are running the tests from.
    • MSMQLocalQueueExistsTest : Check if a local MSMQ private queue exists.
    • MD5ChecksumTest : Check an MD5 digest of a file. This is for file integrity checking.
    • SHA1ChecksumTest : Check an SHA1 digest of a file. This is for file integrity checking.
    • SHA256ChecksumTest : Check an SHA256 digest of a file. This is for file integrity checking.
    • WindowsServiceExistsTest : Check that a windows service exists in the machine the tests are running from.
    • WindowsServiceStatusTest : Check the Status of a windows service, Running, Stopped etc.
    • WindowsRemoteServiceExistsTest : Check that a windows service exists on a remote machine.
    • WindowsRemoteServiceStatusTest : Check the status of a remote windows service, Running, Stopped etc.
    • IISInstalledTest : Check that the IIS web server is installed on the machine the tests are running from.
    • IISRunningTest : Check that the IIS web server is running on the machine the tests are running from.
    • IISVersionTest : Check the version of IIS that is installed.
    • IISDoesWebsiteExistTest : Does a website exist in the instance of IIS.
    • UserInActiveDirectoryTest : Check that a user is in Active Directory for a domain.
    • NetworkPingTest : Ping a network address.
    • AssemblyVersionNumberTest : Check the version of a names .NET assembly.

The Smoke Tester Solution Structure and your First Test

Recently I open sourced a very useful tool called the Post Deployment Smoke Tester. The Post Deployment Smoke Tester is a tool that allows you to run a suite of tests on your environment after you have deployed a piece of software. These tests are invaluable in a large corporate enterprise as more often than not, the people who are doing your deployments are not the original developers.

Out of the box the tool contains many tests that should be immediately useful to you, but you may wish to add in your own. It is early days for this tool so we wont have provided everything that is possible out of the box. If you do need to add in a new test type then you can do so very easily.

If you do want to add or amend any of the tests, then this short article will help you navigate around the Smoke Tester solution structure.

The Smoke Tester tool is split into 4 main components. TestConfiguration, InstallationSmokeTest, ConfigurationTests and CommonCode. The relations-ships between these 4 modules are shown below.

Architecture Diagram for the Smoke Tester Modules
Architecture Diagram for the Smoke Tester Modules

Both TestConfiguration and InstallationSmokeTest are your test editor/runners. Generally you won’t have much need to change these unless you want to add some extra functionality. You main areas of interest will most likely be the ConfigurationTests and CommonCode assemblies. This is where you modify or implement new test types.

%d bloggers like this: