Skip to content

Commit

Permalink
Introduced custom exceptions and better error handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkCiliaVincenti committed Nov 27, 2021
1 parent 0e027d6 commit dbfdf9b
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Samples/CertbotSample/CertbotSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<ItemGroup>
<PackageReference Include="NetworkPorts" Version="1.0.5" />
<PackageReference Include="TlsCertificateLoader" Version="1.1.4" />
<PackageReference Include="TlsCertificateLoader" Version="1.1.7" />
</ItemGroup>

</Project>
26 changes: 24 additions & 2 deletions Samples/CertbotSample/Worker.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Microsoft.Extensions.FileProviders;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using TlsCertificateLoader.Exceptions;

namespace CertbotSample
{
Expand Down Expand Up @@ -33,12 +35,32 @@ private async void CertificatesRefreshed(object state)
if (isWww)
{
ChangeToken(_fileProviderWww, true);
TlsCertificateLoader.RefreshAdditionalCertificates(wwwHostname);
try
{
TlsCertificateLoader.RefreshAdditionalCertificates(wwwHostname);
Debug.WriteLine($"Additional certificates for {wwwHostname} refresh successful");
}
catch (AdditionalCertificatesNotInitializedException)
{
Debug.WriteLine($"Additional certificates for {wwwHostname} refresh failed because initialization did not happen");
}
catch (AdditionalCertificatesNotFoundException ex)
{
Debug.WriteLine($"Additional certificates for {ex.HostName} refresh failed because the certificate was not added");
}
}
else
{
ChangeToken(_fileProvider, false);
TlsCertificateLoader.RefreshDefaultCertificates();
try
{
TlsCertificateLoader.RefreshDefaultCertificates();
Debug.WriteLine($"Default certificates refresh successful");
}
catch (DefaultCertificatesNotInitializedException)
{
Debug.WriteLine($"Default certificates refresh failed because initialization did not happen");
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;

namespace TlsCertificateLoader.Exceptions
{
/// <summary>
/// The exception that is thrown when the additional certificates requested are not found in the dictionary.
/// </summary>
[Serializable]
public sealed class AdditionalCertificatesNotFoundException : KeyNotFoundException
{
/// <summary>
/// The hostname provided
/// </summary>
public string HostName { get; internal set; }

internal AdditionalCertificatesNotFoundException(string hostname) : base("Additional certificates not found.")
{
HostName = hostname;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace TlsCertificateLoader.Exceptions
{
/// <summary>
/// The exception that is thrown when additional certificates are not initialized.
/// </summary>
[Serializable]
public sealed class AdditionalCertificatesNotInitializedException : InvalidOperationException
{
internal AdditionalCertificatesNotInitializedException() : base("Additional certificates not initialized.")
{ }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace TlsCertificateLoader.Exceptions
{
/// <summary>
/// The exception that is thrown when the default certificates are not initialized.
/// </summary>
[Serializable]
public sealed class DefaultCertificatesNotInitializedException : InvalidOperationException
{
internal DefaultCertificatesNotInitializedException() : base("Default certificates not initialized.")
{ }
}
}
51 changes: 39 additions & 12 deletions TlsCertificateLoader/TlsCertificateLoader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using TlsCertificateLoader.Exceptions;
using TlsCertificateLoader.Models;

namespace TlsCertificateLoader
Expand Down Expand Up @@ -37,6 +38,10 @@ public void RefreshDefaultCertificates(string defaultFullChainPemFilePath, strin
/// </summary>
public void RefreshDefaultCertificates()
{
if (_defaultCertificateHolder == null)
{
throw new DefaultCertificatesNotInitializedException();
}
_defaultCertificateHolder.RefreshCertificates();
}

Expand All @@ -48,21 +53,22 @@ public void RefreshDefaultCertificates()
/// <param name="privateKeyPemFilePath">The full path to the private key .pem file (e.g. the privkey.pem generated by Certbot)</param>
public void AddAdditionalCertificates(string hostname, string fullChainPemFilePath, string privateKeyPemFilePath)
{
if (_additionalCertificateHolders == null)
{
_additionalCertificateHolders = new(StringComparer.OrdinalIgnoreCase);
}

_additionalCertificateHolders ??= new(StringComparer.OrdinalIgnoreCase);
_additionalCertificateHolders.Add(hostname, new(fullChainPemFilePath, privateKeyPemFilePath));
}

/// <summary>
/// Remove an additional certificate collection
/// </summary>
/// <param name="hostname">The hostname for which the certificate collection was added</param>
public void RemoveAdditionalCertificates(string hostname)
/// <returns><see langword="true"/> if the additional certificate is successfully found and removed; otherwise, <see langword="false"/>.</returns>
public bool RemoveAdditionalCertificates(string hostname)
{
_additionalCertificateHolders.Remove(hostname);
if (_additionalCertificateHolders == null)
{
throw new AdditionalCertificatesNotInitializedException();
}
return _additionalCertificateHolders.Remove(hostname);
}

/// <summary>
Expand All @@ -73,10 +79,20 @@ public void RemoveAdditionalCertificates(string hostname)
/// <param name="privateKeyPemFilePath">The full path to the private key .pem file (e.g. the privkey.pem generated by Certbot)</param>
public void RefreshAdditionalCertificates(string hostname, string fullChainPemFilePath, string privateKeyPemFilePath)
{
var certificateHolder = _additionalCertificateHolders[hostname];
certificateHolder.FullChainPemFilePath = fullChainPemFilePath;
certificateHolder.PrivateKeyPemFilePath = privateKeyPemFilePath;
certificateHolder.RefreshCertificates();
if (_additionalCertificateHolders == null)
{
throw new AdditionalCertificatesNotInitializedException();
}

if (_additionalCertificateHolders.TryGetValue(hostname, out var certificateHolder))
{
certificateHolder.FullChainPemFilePath = fullChainPemFilePath;
certificateHolder.PrivateKeyPemFilePath = privateKeyPemFilePath;
certificateHolder.RefreshCertificates();
return;
}

throw new AdditionalCertificatesNotFoundException(hostname);
}

/// <summary>
Expand All @@ -85,7 +101,18 @@ public void RefreshAdditionalCertificates(string hostname, string fullChainPemFi
/// <param name="hostname">The hostname for which the certificate collection was added</param>
public void RefreshAdditionalCertificates(string hostname)
{
_additionalCertificateHolders[hostname].RefreshCertificates();
if (_additionalCertificateHolders == null)
{
throw new AdditionalCertificatesNotInitializedException();
}

if (_additionalCertificateHolders.TryGetValue(hostname, out var certificateHolder))
{
certificateHolder.RefreshCertificates();
return;
}

throw new AdditionalCertificatesNotFoundException(hostname);
}

internal CertificateHolder GetCertificateHolder(string hostname)
Expand Down
8 changes: 4 additions & 4 deletions TlsCertificateLoader/TlsCertificateLoader.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
<RepositoryUrl>https://github.com/MarkCiliaVincenti/TlsCertificateLoader.git</RepositoryUrl>
<PackageProjectUrl>https://github.com/MarkCiliaVincenti/TlsCertificateLoader</PackageProjectUrl>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Version>1.1.4</Version>
<Version>1.1.7</Version>
<PackageIcon>logo.png</PackageIcon>
<PackageReleaseNotes>Bumped NetworkPorts package in sample project.</PackageReleaseNotes>
<PackageReleaseNotes>Introduced custom exceptions and better error handling.</PackageReleaseNotes>
<Description>Allows loading of TLS (HTTPS) certificates for .NET 6.0 Kestrel web applications, allowing for refreshing of certificates as well as compatibility with HTTP/3. Fully compatible with certificates obtained by Certbot.</Description>
<Copyright>© 2021 Mark Cilia Vincenti</Copyright>
<PackageTags>HTTPS,TLS,SSL,Kestrel,HTTP3,HTTP/3,certificates,security,net6,net6.0,Certbot,aspnetcore</PackageTags>
<RepositoryType>git</RepositoryType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<AssemblyVersion>1.1.4.0</AssemblyVersion>
<FileVersion>1.1.4.0</FileVersion>
<AssemblyVersion>1.1.7.0</AssemblyVersion>
<FileVersion>1.1.7.0</FileVersion>
<PackageReadmeFile>README.md</PackageReadmeFile>
<IsPackable>true</IsPackable>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
Expand Down

0 comments on commit dbfdf9b

Please sign in to comment.