Updating OwaspHeaders.Core to Use the Builder Pattern

Jamie Taylor
Updating OwaspHeaders.Core to Use the Builder Pattern Header ImageSource: https://unsplash.com/photos/RkJF2BMrLJc Copyright 2017: William Bout (@williambout)

Today’s header image was created by William Bout at Unsplash

The keen-eyed amongst you will have noticed that I released a new version of my OwasHeaders.Core middleware towards the end of February. It’s now at version 3.0.0.1, which is really cool.

For those of you who might not know

or might not remember

I’ve written about my OwaspHeaders.Core project here before, as part of a long form tutorial on how to write ASP NET Core middleware.

I thought I’d take a little time to discuss the changes that I’d made and why I made them. Also, I’m going introduce the builder pattern and where it is used throughout ASP NET Core.

If you want to skip straight to the new stuff in the OwaspHeaders.Core project, click here

What Is The Builder Pattern

All software

at least all good, well engineered software

is built using software engineering and design patterns. In the same way that you wouldn’t necessarily buy a house without doors, you wouldn’t build software without using patterns.

You can think of software design patterns as being abstract ways of designing very common functionality. Just like how an architect will design a building using reusable patterns (a number of walls, a floor, a ceiling, some kind of internal support structure), but one architect may design their building to look completely fresh and new whereas another architect may favour an older style.

The same thing can be said about software. Each application/game/website we interact with will be built from a set abstract, yet simple, designs. The presence of these common designs makes the process of building software faster, and enables more detailed discussion about the process.

Most of the design patterns that we use in software development these days are based on those published in Design Patterns: Elements of Reusable Object-Oriented Software by a group of developers who became known as the “Gang of Four”:

  • Erich Gamma
  • Richard Helm
  • Ralph Johnson
  • John Vlissides

Together they helped to design the basic blueprints for every component of every piece of software that any of us have ever interacted with, and the builder pattern is one such design.

OK, So What Is The Builder Pattern?

As you add more and more members to a class, you need to give them an initial value.

As an example, let’s say that you had a catalogue of items for sale and wanted to represent them in C# objects. You could start with something like this:

public class CatalogueItem
{
public int Id { get; set; }
public double Price { get; set; }
public string Name { get; set; }
public CatalogueItem(int id, double price, string name)
{
Id = id;
Price = price;
Name = name;
}
}

Each member has it’s value explicitly set in the constructor. Now lets add a description to the model

public class CatalogueItem
{
public int Id { get; set; }
public double Price { get; set; }
public string Name { get; set; }
public string Descripton { get; set; }
public CatalogueItem(int id, double price, string name, string description)
{
Id = id;
Price = price;
Name = name;
Description = description;
}
}

Not only did we have to add the member, but we had to add it to the constructor too (highlighted). What if we needed to add a collection of categories?

public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
public class CatalogueItem
{
public int Id { get; set; }
public double Price { get; set; }
public string Name { get; set; }
public string Descripton { get; set; }
public List<Category> Categories { get; set; }
public CatalogueItem(int id, double price, string name, string description, List<Category> categories)
{
Id = id;
Price = price;
Name = name;
Description = description;
Categories = categories;
}
}

Again, we’ve had to add three more lines just for our new member (not counting the declaration of the Category class).

On top of that, the places where we’ve wanted to create a new instance of the CatalogueItem class have gotten more complex:

// CatalogueItem version 1
var catalogueItemV1 = new CatalogueItem(1, 9.99, "V1 catalogue item");
// CatalogueItem version 2
var catalogueItemV2 = new CatalogueItem(2, 12.99, "V2 catalogue item",
"A V2 catalogue item, which has a description, too");
// CatalogueItem version 3
var categoryList = new List<Categories>()
{
new Category(1, "Toys"),
new Category(2, "Games"),
new Category(3, "Video Games");
};
var catalogueItemV3 = new CatalogueItem(3, 14.99, "V3 catalogue item",
"A V3 catalogue item, which has a description and some categories",
categoryList);

Except that since our CatelogueItem class has a single constructor which takes five parameters, the first two declarations are now no longer correct. We either have to put the other two constructors back or add null or default values in place of the missing arguments.

public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
public class CatalogueItem
{
public int Id { get; set; }
public double Price { get; set; }
public string Name { get; set; }
public string Descripton { get; set; }
public List<Category> Categories { get; set; }
public CatalogueItem(int id, double price, string name)
{
Id = id;
Price = price;
Name = name;
// what should we set Description and Categories to?
}
public CatalogueItem(int id, double price, string name, string description)
{
Id = id;
Price = price;
Name = name;
Description = description;
// Categories is a list, we need to set it to something.
// Otherwise we'll get a null ref when we try to access it.
// Should we do that here?
}
public CatalogueItem(int id, double price, string name, string description, List<Category> categories)
{
Id = id;
Price = price;
Name = name;
Description = description;
Categories = categories;
}
}

In the above snippet we’ve put the old constructors back (highlighted), but what should we supply as default values to Description and Categories?

// CatalogueItem version 1
var catalogueItemV1 = new CatalogueItem(1, 9.99, "V1 catalogue item", null , null);
// CatalogueItem version 2
var catalogueItemV2 = new CatalogueItem(2, 12.99, "V2 catalogue item",
"A V2 catalogue item, which has a description, too", new List<Categories>());
// CatalogueItem version 3
var categoryList = new List<Categories>()
{
new Category(1, "Toys"),
new Category(2, "Games"),
new Category(3, "Video Games");
};
var catalogueItemV3 = new CatalogueItem(3, 14.99, "V3 catalogue item",
"A V3 catalogue item, which has a description and some categories",
categoryList);

In the above snippet, we’ve gone the other way: we’ve kept the five parameter constructor and included null or default values in all calls to the constructor.

Neither of these are optimal.

by the way, if you look into COM or the Win32API, you’ll see a lot of null arguments because of stuff like this

This exact problem is what the builder pattern aims to solve.

The idea is that you create a separate class (usually a static one, but it doesn’t have to be) which will act as a builder or creator for your intended class rather than having overloaded constructors all over the place. Let’s use the previous example and you’ll see what I mean.

We have the same members in our CatalogueItem class, but this time we’ll remove all of the constructors and replace it with a default one (with a slight twist):

public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
public class CatalogueItem
{
public int Id { get; set; }
public double Price { get; set; }
public string Name { get; set; }
public string Descripton { get; set; }
public List<Category> Categories { get; set; }
public CatalogueItem()
{
// if we don't supply any Categories, we need a constructed
// List here, Otherwise we'll get a null ref when we attempt
// to access it.
Categories = new List<Categories>();
}
}

Then we’ll create a static class which will build an instance of the CatalogueItem class for us:

public static class CatalogueItemBuilder
{
public static CatalogueItem CreateBuilder()
{
return new CatalogueItem();
}
public static WithId(this CatalogueItem cItem, int id)
{
cItem.Id = id;
}
public static WithName(this CatalogueItem cItem, string name)
{
cItem.Name = name
}
public static WithPrice(this CatalogueItem cItem, double price)
{
cItem.Price = price;
}
public static WithDescription(this CatalogueItem cItem, string Description)
{
cItem.Description = description;
}
public static WithCategories(this CatalogueItem cItem, List<Category> categories)
{
cItem.Categories = categories;
}
}

What we’ve done here is created a selection of extension methods. These are methods which we are creating separately from our original class (CatalogueItem) but behave like. and can be consumed as if, they are found within the original class. They’re called extension methods because they extend the original class by adding new functionality to it.

And finally, we’ll consume the builder and use it to create the same instances as before:

// CatalogueItem version 1
var catalogueItemV1 = CatalogueItemBuilder
.CreateBuilder()
.WithId(1)
.WithName("V1 catalogue item")
.WithPrice(9.99);
// CatalogueItem version 2
var catalogueItemV2 = CatalogueItemBuilder
.CreateBuilder()
.WithId(2)
.WithName("V2 catalogue item")
.WithPrice(12.99);
.WithDescription("A V2 catalogue item, which has a description, too");
// CatalogueItem version 3
var categoryList = new List<Categories>()
{
new Category(1, "Toys"),
new Category(2, "Games"),
new Category(3, "Video Games");
};
var catalogueItemV3 = CatalogueItemBuilder
.CreateBuilder()
.WithId(3)
.WithName("V3 catalogue item")
.WithPrice(12.99)
.WithDescription("A V3 catalogue item, which has a description and some categories");
.WithCategories(categoryList);

We’ve added a slight bonus here, in that we’ve also created a Fluent interface, meaning that the extension methods read almost like English and they can be daisy-chained together, with each subsequent call adding something to the returned object of the previous call.

The builder pattern helps us to build up the instances of our class, by allowing us to only supply the values that we need for that particular instance without having to worry whether there is a constructor overload supplied for us which matches the use case.

Let’s say that we wanted to create an instance of the CatalogueItem with only the following values:

  • an Id of 4
  • a name of “mystery item”
  • a category list which contained “Shed Equipment” and “Shovels”

Our original list of constructors doesn’t allow us to do that, unless we supply some null or default values making the call to the constructor hard to reason with. However, if we use the builder pattern:

var categoryList = new List<Categories>()
{
new Category(3, "Shed Equpiment"),
new Category(4, "Shovels"),
};
var customCatalogueItem = CatalogueItemBuilder
.CreateBuilder()
.WithId(4)
.WithName("mystery item")
.WithCategories(categoryList);

Hopefully, you’re starting to see how you can use the builder pattern to simplify creating instances of objects.

even if I’ve used a horridly contrived example

How Does It Apply to ASP NET Core?

Ever since ASP NET Core version 2.0, we’ve been using the builder pattern but you may not have realised it. Let’s take a look at the program.cs of a new ASP NET Core 2.0 application:

namespace aspNetCore2Example
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}

I’ve intentionally left out the using statements, so that I could keep the snippet short

Taking a look at the BuildWebHost method, we can see that it makes a call to a method called CreateDefaultBuilder on a WebHostclass, but what is it?

Well, firstly it looks like this:

// the following code was copied from:
// https://github.com/aspnet/MetaPackages/blob/release/2.0.0/src/Microsoft.AspNetCore/WebHost.cs
// which has the following copyright and licensing information attached to it:
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public static IWebHostBuilder CreateDefaultBuilder()
{
return WebHost.CreateDefaultBuilder((string[]) null);
}

But that doesn’t tell us anything, except that it calls an overloaded version of the same CreateDefaultBuilder method:

// the following code was copied from:
// https://github.com/aspnet/MetaPackages/blob/release/2.0.0/src/Microsoft.AspNetCore/WebHost.cs
// which has the following copyright and licensing information attached to it:
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
return new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((Action<WebHostBuilderContext, IConfigurationBuilder>) ((hostingContext, config) =>
{
IHostingEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", true, true)
.AddJsonFile(string.Format("appsettings.{0}.json", (object) hostingEnvironment.EnvironmentName), true, true);
if (hostingEnvironment.IsDevelopment())
{
Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
if (assembly != (Assembly) null)
{
config.AddUserSecrets(assembly, true);
}
}
config.AddEnvironmentVariables();
if (args == null)
{
return;
}
config.AddCommandLine(args);
}))
.ConfigureLogging((Action<WebHostBuilderContext, ILoggingBuilder>) ((hostingContext, logging) =>
{
logging.AddConfiguration((IConfiguration) hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
}))
.UseIISIntegration()
.UseDefaultServiceProvider((Action<WebHostBuilderContext, ServiceProviderOptions>) ((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment()));
}
}

by the way, here’s a link to the CreateDefaultBuilder method on GitHub

I’ve added newlines and curly braces ({ and }) in order to make it easier to read. But you should hopefully see that this method is part builder pattern. This method calls the WebHostBuilder method:

// The following code was copied from the ASP NET Core gitHub repo which has
//the following copyright and licensing information attached to it:
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public WebHostBuilder()
{
this._hostingEnvironment = (IHostingEnvironment) new HostingEnvironment();
this._configureServicesDelegates = new List<Action<WebHostBuilderContext, IServiceCollection>>();
this._configureAppConfigurationBuilderDelegates = new List<Action<WebHostBuilderContext, IConfigurationBuilder>>();
this._config = (IConfiguration) new ConfigurationBuilder()
.AddEnvironmentVariables("ASPNETCORE_").Build();
if (string.IsNullOrEmpty(this.GetSetting(WebHostDefaults.EnvironmentKey)))
{
this.UseSetting(WebHostDefaults.EnvironmentKey, Environment.GetEnvironmentVariable("Hosting:Environment")
?? Environment.GetEnvironmentVariable("ASPNET_ENV"));
}
if (string.IsNullOrEmpty(this.GetSetting(WebHostDefaults.ServerUrlsKey)))
{
this.UseSetting(WebHostDefaults.ServerUrlsKey, Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS"));
}
this._context = new WebHostBuilderContext()
{
Configuration = this._config
};
}

However this does not use the builder pattern.

But the method called after this one do use the builder pattern:

// the following code was copied from:
// https://github.com/aspnet/MetaPackages/blob/release/2.0.0/src/Microsoft.AspNetCore/WebHost.cs
// which has the following copyright and licensing information attached to it:
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
return new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((Action<WebHostBuilderContext, IConfigurationBuilder>) ((hostingContext, config) =>
{

What’s great about this, is that it’s all done behind the scenes for you. Unless you dive into the source code, you’d never know that ASP NET Core 2.0 used a builder pattern to provide you with a default WebHost.

How Did I Use It In OwaspHeaders.Core?

All of that information is jolly good

did you read through it or just jump down to this bit?

but none of that is about OwaspHeaders.Core. Well, let’s change that right now.

My primary focus for using the builder pattern was to move away from using a json file for configuration. I did this for two reasons and both are related to changing the json file.

If you take a look at the example application (included in the GitHub repo) from before I made any of the Builder Pattern changes

we’re talking before commit #e9e8b05

you’ll see that the json configuration for the middleware (secureHeaderSettings.json) was included in the Program.cs like this:

public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("secureHeaderSettings.json", optional: true, reloadOnChange: true);
})
.UseStartup<Startup>()
.Build();

The most interesting part is the highlighted line; even then the most interesting part of the highlighted line is: reloadOnChange: true. This meant that if someone changed the secureHeaderSettings.json file, then the entire application which was consuming the OwaspeHeaders.Core middleware would be shut down and restarted.

Think about that for a second. If a big application was serving loads of traffic

if you’re gonna think about it, why not think big?

and someone changed the secureHeaderSettings.json file, then the site would be taken down and started back up. Which is disastrous. Especially since the settings for the middleware would be a compile/build time constant – you wouldn’t realistically want it changing at run-time.

Replacing the json file with a number of methods would have been hard, had I not decided to use the builder pattern. OwaspHeaders.Core is made of several POCO models which are consumed in the middleware’s Invoke method to inject headers in to the generated response.

if parts of this are gobbledegook, then I’d recommend taking a look back at my article on middleware in ASP NET Core

These models need to be present, and values for their members need to be supplied, in order for the relevant headers to be injected. To see this more clearly, let’s take a look at the Invoke method:

public async Task Invoke(HttpContext httpContext)
{
if (_config == null)
{
throw new ArgumentException([email protected]"Expected an instance of the
{nameof(SecureHeadersMiddlewareConfiguration)} object.");
}
if (_config.UseHsts)
{
httpContext.TryAddHeader(Constants.StrictTransportSecurityHeaderName,
_config.HstsConfiguration.BuildHeaderValue());
}
if (_config.UseXFrameOptions)
{
httpContext.TryAddHeader(Constants.XFrameOptionsHeaderName,
_config.XFrameOptionsConfiguration.BuildHeaderValue());
}

I’ve highlighted the lines which inject the HSTS header, let’s take a look at the BuildHeaderValue for it:

/// <summary>
/// Builds the HTTP header value
/// </summary>
/// <returns>A string representing the HTTP header value</returns>
public string BuildHeaderValue()
{
var stringBuilder = new StringBuilder();
stringBuilder.Append("max-age=");
stringBuilder.Append(MaxAge);
stringBuilder.Append(IncludeSubDomains ? "; includeSubDomains" : string.Empty);
return stringBuilder.ToString();
}

From the BuildHeaderValue method, we can assume that the HstsConfiguration POCO has two members:

  • MaxAge
  • IncludeSubdomains

Both of these will need a value when we decide to use the HSTS header, and the default values provided by C# might not be the ones we want. So we’ll need a method to set them up with default values (if the consumer doesn’t supply them). We also need an easy way to include the HSTS header without forcing the user to add hundreds of lines to their Configure method in their Startup class.

Enter: BuildDefaultConfiguration

This is where the builder pattern comes into play. Over in the SecureHeaderMiddlewareExtensions class, I’ve added a method called BuildDefaultConfiguration which looks like this:

public static SecureHeadersMiddlewareConfiguration BuildDefaultConfiguration()
{
return SecureHeadersMiddlewareBuilder
.CreateBuilder()
.UseHsts()
.UseXFrameOptions()
.UseXSSProtection()
.UseContentTypeOptions()
.UseContentDefaultSecurityPolicy()
.UsePermittedCrossDomainPolicies()
.UseReferrerPolicy()
.Build();
}

This method uses the builder pattern to call a number of extension methods which set up the various member values for all of the POCOs that the middleware requires. For instance, here is the code for the UseHsts method:

public static SecureHeadersMiddlewareConfiguration UseHsts
(this SecureHeadersMiddlewareConfiguration config,
int maxAge = 63072000, bool includeSubDomains = true)
{
config.UseHsts = true;
config.HstsConfiguration = new HstsConfiguration(maxAge, includeSubDomains);
return config;
}

Here, I’m using a neat C# feature called Optional Arguments to provide the default values for both  members of the HstsConfiguration POCO (MaxAge and IncludeSubdomains). This way the consumer doesn’t have to supply values for either of these parameters when the want to add the HSTS header.

I’ve chosen the default values based on the values given in the OWASP Secure Headers Best Practise guide for HSTS. I’ve done the same thing for all of the other headers which the middleware supports, too.

In the sample which I’ve included in the GitHub repo, I’ve added and configured the middleware like this:

public void Configure(IApplicationBuilder app,
IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.GnuTerryPratchett();
app.UseSecureHeadersMiddleware(SecureHeadersMiddlewareExtensions.BuildDefaultConfiguration());
app.UseMvc();
}

Which calls the default builder and adds the OWASP recommended values for each of the secure headers. But a consumer of the middleware could use the builder pattern to set up their own configuration like so:

public void Configure(IApplicationBuilder app,
IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.GnuTerryPratchett();
var defaultSelfCsp = new List<ContenSecurityPolicyElement>
{
new ContenSecurityPolicyElement()
{
CommandType = CspCommandType.Directive,
DirectiveOrUri = "self"
}
};
var secureHeadersConfiguration = SecureHeadersMiddlewareBuilder
.CreateBuilder()
.UseHsts(2500, false)
.UseXFrameOptions(XFrameOptions.sameorigin)
.UseXSSProtection(XssMode.zero, "https://some-uri.me")
.UseContentTypeOptions()
.UseContentSecurityPolicy(null, blockAllMixedContent:true,
upgradeInsecureRequests:false, referrer: "mozilla", reportUri: "https://some-uri.me")
.SetCspUris(defaultSelfCsp, CspUriType.DefaultUri)
.UsePermittedCrossDomainPolicies(XPermittedCrossDomainOptionValue.all)
.UseReferrerPolicy(ReferrerPolicyOptions.unsafeUrl)
.Build();
app.UseSecureHeadersMiddleware(secureHeadersConfiguration);
app.UseMvc();
}

Note: the above configuration is provided as an example and may not improve the stability or security of your application in any way, shape, or form.

This is cluttering up the Startup class and it would be recommended to move the highlighted code to an extension method – perhaps called something like BuildAndConsumeCustomSecureHeaderConfiguration

now that’s what I call a catchy method name


I really dig using the Builder Pattern, especially when my constructor calls could end up multiplying past the point where it’s considered silly

usually when there are 4 or 5 arguments

and into the ludicrous. Plus, it helps to keep the code simpler and easy to read – especially if you can implement a Fluent Interface.

Have you used the Builder Pattern before? Was it an afterthought a late breaking feature or was the code you were working on designed to use the Builder Pattern from the get go?

If you’ve never used the Builder Pattern before, why not? Are you more willing to try it out with something, now that you’ve read a little about it and seen a real world example of it?

Have you used my OwaspHeaders.Core NuGet package in an ASP NET Core 2.0 project of yours? I’d love to hear about it if you have. Was it intuitive to implement, which version did you use, and did you read the documentation first?

I really would like to know if any of you have used it in your projects. I’m guessing that some of you must have, because it currently has 2,302 total downloads (at the time of writing).

if it’s closed source and you can’t really talk about it, tweet at me with the hashtag #OwaspHeadersCoreUser

Jamie Taylor
A .NET developer specialising in ASP.NET MVC websites and services, with a background in WinForms and Games Development. When not programming using .NET, he is either learning about .NET Core (and usually building something cross platform with it), speaking Japanese to anyone who'll listen, learning about languages, writing for his non-dev blog, or writing for a blog about video games (which he runs with his brother)