ConfigMgr 2007 Distribution Points Load Testing

At Microsoft, we have 280,000+ client machines that are managed worldwide and in our past life we were planning to scale our service to other companies client machines as well.  As part of the platform team responsible for ensuring that our ConfigMgr 2007 infrastructure could scale to support hundreds of thousands of clients (and even millions), we had to find a way to solve a rather non-trivial mechanism for testing our Distribution Points (DP) to ensure they could effectively manage the connections thrown at them by the CCMEXEC (SMS) client agent.

In the next 3 to 4 posts, I’m going to outline how we creatively came up with a mechanism to generate load testing against our DPs.  The one caveat is this load testing is only for HTTP-based traffic that is unsecure (Mixed-mode) or secure (Native mode).

Let’s get started…

Required Tools

In this first post, I want to share with you what applications we used in order to do this testing and the reason we selected these tools.  The following table lists the tools we used to build this functionality:

Tool Purpose
Visual Studio 2005/2008 In order to generate load, we wrote code (CertPicker) that would grab randomly from directory certificates stored in PFX format and load the certificate and delete it after using it. These certificates were generated from a trusted Certificate Authority for the DP (NOTE: This is only needed if you are running ConfigMgr 2007 in Native Mode)
ConfigMgr 2007 DP Obviously, you need a DP in as this is the purpose of the load testing. However, you will need to have a valid set of packages (we used various sizes) that are created and already replicated to your DPs
Visual Studio Team System 2008 There are a number of HTTP-based load testing toolsets out on the market but the most comprehensive and flexible is, in my opinion, the Visual Studio Team System. This edition allows you to create Web and Load tests and automatically tracks the performance of your DP and reports this to you. Beyond that, you can easily store them in a database for metric reporting at a later date.
Certificate Authority For ConfigMgr 2007 Native-Mode, you will need to have a Certificate Authority who has a valid client certificate template available to create certificates. Ideally, you would create a number of certificates that are automatically exported to a PFX file for use by your load test.

 

Part I: Compile your CertPicker Code

There are two methods to actually use CertPicker and I’m including source for both of them.  The first is an assembly that can be resourced in your Web tests (see future post to understand this concept) but you can also use it as part of a Console application (Command-Line).

Assembly:

Code Snippet

  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Security.Cryptography.X509Certificates;

  6. using System.IO;

  7. namespace CAdCertPicker

  8. {

  9.     public class CertPicker

  10.     {

  11.         private string _certLocation;

  12.         private static  Random _rand = new Random((DateTime.Now.Minute ^ DateTime.Now.Millisecond) * DateTime.Now.Second);

  13.         public CertPicker(string certLocation)

  14.         {

  15.             if (string.IsNullOrEmpty(certLocation))

  16.             {

  17.                 throw new ArgumentNullException("certLocation");

  18.             }

  19.             _certLocation = certLocation;

  20.         }

  21.         public X509Certificate2 GetRandomCertificate(string certPassword)

  22.         {

  23.             return GetRandomCertificate(_certLocation, certPassword);

  24.         }

  25.         public static X509Certificate2 GetRandomCertificate(string certLocation, string certPassword)

  26.         {

  27.             string[] files = Directory.GetFiles(certLocation, "*.pfx");

  28.             if (files.Length > 0)

  29.             {

  30.                 if (certPassword == null)

  31.                 {

  32.                     return new X509Certificate2(File.ReadAllBytes(files[_rand.Next(0, files.Length - 1)]));

  33.                 }

  34.                 else

  35.                 {

  36.                     return new X509Certificate2(File.ReadAllBytes(files[_rand.Next(0, files.Length - 1)]), certPassword);

  37.                 }

  38.             }

  39.             throw new InvalidOperationException("No certificates ending in *.pfx in '" + certLocation + "'");

  40.         }

  41.         public void InstallCertificate(X509Certificate2 cert)

  42.         {

  43.             InstallCertificate(cert, StoreLocation.LocalMachine);

  44.         }

  45.         public void InstallCertificate(X509Certificate2 cert, StoreLocation storeLocation)

  46.         {

  47.             X509Store store = new X509Store(StoreName.My, storeLocation);

  48.             try

  49.             {

  50.                 store.Open(OpenFlags.ReadWrite);

  51.                 store.Add(cert);

  52.             }

  53.             finally

  54.             {

  55.                 store.Close();  

  56.             }

  57.         }

  58.         public X509Certificate2 InstallRandomCertificate(string certPassword)

  59.         {

  60.             X509Certificate2 cert = GetRandomCertificate(certPassword);

  61.             InstallCertificate(cert);

  62.             return cert;

  63.         }

  64.         public X509Certificate2 InstallRandomCertificate(string certPassword, StoreLocation storeLocation)

  65.         {

  66.             X509Certificate2 cert = GetRandomCertificate(certPassword);

  67.             InstallCertificate(cert, storeLocation);

  68.             return cert;

  69.         }

  70.         public void RemoveCert(X509Certificate2 cert, StoreLocation storeLocation)

  71.         {

  72.             RemoveCertificate(cert, storeLocation);

  73.         }

  74.         public void RemoveCert(X509Certificate2 cert)

  75.         {

  76.             RemoveCertificate(cert, StoreLocation.LocalMachine);

  77.         }

  78.         public static X509Certificate2 InstallRandomCertificate(string certLocation, string certPassword)

  79.         {

  80.             return InstallRandomCertificate(certLocation, certPassword, StoreLocation.LocalMachine);

  81.         }

  82.         public static X509Certificate2 InstallRandomCertificate(string certLocation, string certPassword, StoreLocation storeLocation)

  83.         {

  84.             CertPicker certPicker = new CertPicker(certLocation);

  85.             return certPicker.InstallRandomCertificate(certPassword, storeLocation);

  86.         }

  87.         public static void RemoveCertificate(X509Certificate2 cert)

  88.         {

  89.             RemoveCertificate(cert, StoreLocation.LocalMachine);

  90.         }

  91.         public static void RemoveCertificate(X509Certificate2 cert, StoreLocation storeLocation)

  92.         {

  93.             X509Store store = new X509Store(StoreName.My, storeLocation);

  94.             try

  95.             {

  96.                 store.Open(OpenFlags.ReadWrite);

  97.                 store.Remove(cert);

  98.             }

  99.             finally

  100.             {

  101.                 store.Close();

  102.             }

  103.         }

  104.     }

  105. }

Console:

Code Snippet

  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using CAdCertPicker;

  6. using System.Security.Cryptography.X509Certificates;

  7. namespace CAdCertPickerConsole

  8. {

  9.     class Program

  10.     {

  11.         static void Main(string[] args)

  12.         {

  13.             // Using it  -- using the static CertPicker methods - there are multiple overloads too.

  14.             X509Certificate2 cert = CertPicker.InstallRandomCertificate(@"C:\Users\bdela\Desktop\HavanaStress_20", "ObjGen", StoreLocation.LocalMachine);

  15.             CertPicker.RemoveCertificate(cert, StoreLocation.LocalMachine);

  16.             // Using it  -- using the static CertPicker methods - there are multiple overloads too.

  17.             CertPicker picker = new CertPicker(@"C:\Users\bdela\Desktop\HavanaStress_20");

  18.             cert = picker.InstallRandomCertificate("ObjGen", StoreLocation.CurrentUser);

  19.             picker.RemoveCert(cert, StoreLocation.CurrentUser);

  20.         }

  21.     }

  22. }

NOTE:  A quick shout out thanks to Brian Delahunty, my resident helper when code doesn’t work\stuck, who helped me with this code.  Irish, you rock!

Part II: Creating your source Certificates for use with CertPicker

In my next post, I’m going to share with you how to create the correct client certificate template on a Microsoft Certificate Authority (CA) that will allow you to generate the correct certificate.  After this, I will share a quick insight into how to write a quick .EXE that requests certificates from the CA automagically based on the template name.

Stay tuned…

-Chris

Digg This