Skip to content

Commit

Permalink
Merge pull request #10 from TerribleDev/expectCt
Browse files Browse the repository at this point in the history
add expect ct
  • Loading branch information
TerribleDev authored Oct 28, 2017
2 parents 72c55bd + 4f4c5d3 commit 6019640
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/HardHat.UnitTests/ExpectCtHeaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using HardHat.Builders;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace HardHat.UnitTests
{
public class ExpectCtHeaderTests
{
[Fact]
public void TestExceptions()
{
Assert.Throws<ArgumentNullException>(() => ExpectCtHeaderBuilder.Build(0, string.Empty));
}

[Fact]
public void TestHeader()
{
var result = ExpectCtHeaderBuilder.Build(0, "/awesome");

Assert.Equal("max-age=0; report-uri=\"/awesome\"", result);
}

[Fact]
public void TestHeaderWithEnforce()
{
var result = ExpectCtHeaderBuilder.Build(0, "/awesome", true);

Assert.Equal("max-age=0; report-uri=\"/awesome\"; enforce", result);
}
}
}
23 changes: 23 additions & 0 deletions src/HardHat/Builders/ExpectCtHeaderBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace HardHat.Builders
{
internal static class ExpectCtHeaderBuilder
{
internal static string Build(ulong maxAge, string reportUri, bool enforce = false)
{
if (string.IsNullOrWhiteSpace(reportUri))
{
throw new ArgumentNullException(nameof(reportUri), "Report URI must have a value");
}
var builder = new StringBuilder($"max-age={maxAge}; report-uri=\"{reportUri}\"");
if (enforce)
{
builder.Append("; enforce");
}
return builder.ToString();
}
}
}
1 change: 1 addition & 0 deletions src/HardHat/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal static class Constants
internal const string semicolon = ";";
internal const string HpKpHeader = "Public-Key-Pins";
internal const string HpKpHeaderReportOnly = "Public-Key-Pins-Report-Only";
internal const string ExpectCt = "Expect-CT";
internal static class Referrers
{
internal const string NoReferrer = "no-referrer";
Expand Down
11 changes: 11 additions & 0 deletions src/HardHat/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ public static IApplicationBuilder UseHsts(this IApplicationBuilder app, TimeSpan
/// <returns></returns>
public static IApplicationBuilder UseHpkp(this IApplicationBuilder app, ulong maxAge, ICollection<PublicKeyPin> keys, bool includeSubDomains = false, string reportUri = "", bool reportOnly = false) => app.UseMiddleware<Hpkp>(maxAge, keys, includeSubDomains, reportUri, reportOnly);

/// <summary>
/// NOTE: This is still in draft spec, browser support maybe very limited
/// <para>Certificate Transparency is an open framework for monitoring and auditing the certificates issued by Certificate Authorities in near real-time. By requiring a CA to log all certificates they generate, site owners can quickly identify mis-issued certificates and it becomes much easier to detect a rogue CA. <see href="https://scotthelme.co.uk/a-new-security-header-expect-ct/"/></para>
/// </summary>
/// <param name="app"></param>
/// <param name="maxAge"> specifies the number of seconds that the browser should cache and apply the received policy for, whether enforced or report-only.</param>
/// <param name="reportUri"> specifies where the browser should send reports if it does not receive valid CT information. This is specified as an absolute URI.</param>
/// <param name="enforce">controls whether the browser should enforce the policy or treat it as report-only mode. The directive has no value so you simply include it or not depending on whether or not you want the browser to enforce the policy or just report on it.</param>
/// <returns></returns>
public static IApplicationBuilder UseCertificateTransparency(this IApplicationBuilder app, ulong maxAge, string reportUri, bool enforce = false) => app.UseMiddleware<ExpectCt>(maxAge, reportUri, enforce);

/// <summary>
/// change or remove the server header.
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions src/HardHat/Middlewares/ExpectCt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using HardHat.Builders;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace HardHat.Middlewares
{
public class ExpectCt
{
private readonly RequestDelegate _next;
private readonly string headerValue;
public ExpectCt(RequestDelegate next, ulong maxAge, string reportUri, bool enforce = false)
{
this._next = next;
if(string.IsNullOrWhiteSpace(reportUri))
{
throw new ArgumentNullException(nameof(reportUri), "Report URI must have a value");
}
headerValue = ExpectCtHeaderBuilder.Build(maxAge, reportUri, enforce);
}

public Task Invoke(HttpContext context)
{
context.Response.Headers[Constants.ExpectCt] = headerValue;
return _next?.Invoke(context);
}
}
}

0 comments on commit 6019640

Please sign in to comment.