Keeping .NET app settings secrets out of source control

Keeping .NET app settings secrets out of source control

Whether your app is a desktop client app or a website, it’s important to keep passwords, connection strings, and API keys out of source control. In .NET, these settings are stored in a app.config or web.config file depending on the type of app you are building and those files would be checked into source control. I’ve done this in the past for many projects. Of course, I never committed production secrets, but it was still a big no-no, but I just never had the time to investigate the proper way to handle this situation…until today.

A quick Google search returned this result: http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure. Config files have a simple way of handling this by adding a file attribute to the appSettings section of the web.config file, like so

<appSettings file="secrets.config">
  <add key="testSetting" value="not a secret" />
</appSettings/>

And the secrets.config file looks like this

<appSettings>
  <add key="secretTestSetting" value="very secret" />
  <add key="testSetting" value="I will overwrite" />
</appSettings>

This is the entire file, it is important that the root element is <appSettings> , otherwise you will get a compile or runtime error. Any new keys defined will be added and any existing keys will overwrite the value from the web.config.

Overwriting values in the web.config is very useful for local development. Since the secrets.config file is never checked in, each developer can keep their own local app settings values without worrying about mistakenly checking them in and overriding the web.config default values. No more commenting out values in your web.config!

The same thing works for the connectionStrings section, except in this case the entire section is overwritten. In fact, the web.config can’t have any elements under it or you will get errors. The web.config will look like this

<connectionStrings configSource="connectionStrings.config">
</connectionStrings>

And the connectionStrings.config will look like this

<connectionStrings>
  <clear/>
  <add name="Database" connectionString="very secret" />
</connectionStrings>

As long as your extra files have the .config extension, IIS will never serve them. Also, you should never add these secrets config files to your project to avoid mistakenly deploying them to your servers. Instead, your release process should deploy secrets files separately from code files.

And finally, always add secrets.config and connectionStrings.config to your .gitignore and to get first-time developers setup with secrets, you could include these files somewhere outside of source control, like a file share.

That’s all! Super easy way to keep all your secrets safe in both desktop and web applications. Find the code here: https://github.com/svarcoe/AppSecretsDemoProject

EmguCV: Rotating face images to align eyes

Sometimes to increase accuracy of face recognition algorithms it’s important to make sure the face is upright. For instance, in this image of Arnold, he is tilting his head, which may make it difficult to recognize him:

One way to pre-process this image is to rotate the it so the face is upright. The fastest way to do that is to find the eyes using a cascade classifier and then finding the angle between the eyes. This method AlignEyes will take an image and return one that is rotated upright:

public static Image<Gray, byte> AlignEyes(Image<Gray, byte> image)
{
     Rectangle[] eyes = EyeClassifier.DetectMultiScale(image, 1.4, 0, new Size(1, 1), new Size(50, 50));
     var unifiedEyes = CombineOverlappingRectangles(eyes).OrderBy(r => r.X).ToList();
     if (unifiedEyes.Count == 2)
     {
           var deltaY = (unifiedEyes[1].Y + unifiedEyes[1].Height/2) - (unifiedEyes[0].Y + unifiedEyes[0].Height/2);
           var deltaX = (unifiedEyes[1].X + unifiedEyes[1].Width/2) - (unifiedEyes[0].X + unifiedEyes[0].Width/2);
           double degrees = Math.Atan2(deltaY, deltaX)*180/Math.PI;
           if (Math.Abs(degrees) < 35)
           {
                   image = image.Rotate(-degrees, new Gray(0));
           }
     }
     return image;
}

EyeClassifier is a cascade classifier using the training file included with EmguCV called “haarcascade_eye_tree_eyeglasses.xml”. You can use whatever training you find works best.

And here is the result (the face has been cropped and masked in this image):

Face Detection for .NET using EmguCV

First of all, let me explain the difference between face “detection” and face “recognition”.  There seems to be a lot of misinformation out there about these two terms and they are not interchangeable.  Face detection is when a computer finds all the faces that appear in an image.  The best algorithm out there right now is Viola-Jones method using cascade classifiers. The Viola-Jones method can actually be trained to detect any object, so it isn’t specific to detecting faces. For instance, it can detect an apple in a given image.

Face recognition is when a computer gives a name to a face image. There are many different algorithms for recognition including Eigen faces, Fischer faces, and Local Binary Pattern Histograms.

Okay, now that you know the difference between detection and recognition, I will show you how to do detection simple using a CascadeClassifier in EmguCV.

First, we need to construct a classifier using some of the built in training files. These can be found under the HaarCascades directory in the EmguCV installation directory. We make a new classifier like this:

private static readonly CascadeClassifier Classifier = new CascadeClassifier("haarcascade_frontalface_alt_tree.xml");

Secondly, classifiers only take grayscale image so we convert our Bgr image to gray:

 Image<Gray, byte> grayImage = image.Convert<Gray, byte>(); 

Finally, we call the DetectMultiScale method on our classifier:

Rectangle[] rectangles = Classifier.DetectMultiScale(grayImage, 1.4, 0, new Size(100,100),new Size(800,800));

Let’s review these parameters because you will probably need to tweak them for your system. The first parameter is the grayscale image. The second parameter is the windowing scale factor. This parameter must be greater than 1.0 and the closer it is to 1.0 the longer it will take to detect faces but there’s a greater chance that you will find all the faces. 1.4 is a good place to start with this parameter.

The third parameter is the minimum number of nearest neighbors. The higher this number the fewer false positives you will get. If this parameter is set to something larger than 0, the algorithm will group intersecting rectangles and only return those that have overlapping rectangle greater than or equal to the minimum number of nearest neighbors. If this parameter is set to 0, all rectangles will be returned and no grouping will happen, which means the results may have intersecting rectangles for a single face.

The last two parameters are the min and max sizes in pixels. The algorithm will start searching for faces with a window 800×800 and it will decrease the window size by the factor of 1.4 until it reaches the min size of 100×100. The bigger the range between the min and max size, the longer the algorithm will take to complete.

The output of the DetectMultiScale function is a set of rectangles that represent where the faces are relative to the input image.
It’s as easy as that. With just a few lines of code, you can detect where all the faces are in any image.

You can download EmguCV here: http://www.emgu.com/wiki/index.php/Main_Page

Could not copy the file “obj\Debug\app.exe” because it was not found

I was in the middle of working on a project and I suddenly started getting the following error:

I tried a complete clean and rebuild. I even tried scorching my workspace but the error would not go away. I read that it might be a problem with Visual Studio extensions so I disabled all my extensions, but no luck.

I then started watching the obj\Debug folder as I did a build. Turns out that the .exe file was getting written, but then it would immediately be deleted before the build could finish. Then I found this:

It turns out that Avast anti-virus thought my program was suspicious and was quarantining it during the build process.  Adding an exclusion for my entire source tree solved this issue.

Next time, I’ll discuss how to solve the issue when installing this same application.

Executing a custom TFS 2010 BuildActivity on the Controller

Most of the time when you create a custom Build Activity for TFS 2010 you want it to run on the Build Agent. Occasionally, you will come across a situation where you need your activity to execute as the very first thing before the build has even started or as the very last thing after the build is finalized. It’s very easy to configure your custom Build Activity to run on the controller. All Build Activities classes have the BuildActivity attribute. This attribute takes one argument, HostEnvironmentOption, which has four options: Agent, Controller, All, or None.

[BuildActivity(HostEnvironmentOption.All)]
public sealed class SendEmailActivity : CodeActivity
{

By setting the HostEnvironmentOption to All or Controller we can run our custom Build Activity on the build controller. The Agent option will restrict the activity to the build agent. Most of the time I use the All option unless I have a good reason not to.

If you don’t use the right HostEnvironmentOption you will get an error like the following:

TF215097: An error occurred while initializing a build for build definition \Internal\Test Build Definition: The build process failed validation. Details: Validation Error: The private implementation of activity ‘1: DynamicActivity’ has the following validation error: TF28000: Activity ‘SendEmailActivity’ must be used in the context of an AgentScope.