Skip to content

Commit

Permalink
Add Docker and TLS terminating proxy support
Browse files Browse the repository at this point in the history
WE2-835

Signed-off-by: Mart Somermaa <[email protected]>
  • Loading branch information
mrts committed Nov 17, 2023
1 parent 13da401 commit c3f1417
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/dotnet-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ jobs:

- name: Test
run: dotnet test --no-restore --verbosity normal src/WebEid.AspNetCore.Example.sln

- name: Test building Docker image
run: docker build -t web-eid-asp-dotnet-example src/
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Web eID specific
*.swp
/src/WebEid.AspNetCore.Example/DigiDoc/

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
90 changes: 90 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,93 @@ You are running in the `Development` profile, but you have not created an empty
#### Why do I get the `System.BadImageFormatException: An attempt was made to load a program with an incorrect format` error during signing?

You are using `libdigidocpp` DLLs for the wrong architecture. Copy files from the `x64` subfolder of the `libdigidocpp` installation folder to right place as described in the section _3. Setup the `libdigidocpp` library for signing_ above. In case you get this error while developing a custom 32-bit application, copy files from the `x86` subfolder instead.

## Building and running with Docker on Ubuntu Linux

This section covers the steps required to build the application on an Ubuntu Linux environment and run it using Docker.

### Prerequisites

Before you begin, ensure you have the following installed on your system:

- .NET SDK 7.0
- libdigidocpp-csharp

You can install them using the following command:

```sh
sudo apt install dotnet-sdk-7.0 libdigidocpp-csharp
```

### Building the application

To build the application, follow these steps:

1. Navigate to the `src` directory:

```sh
cd src
```

2. Copy the necessary DigiDoc C# library files into your project:

```sh
cp /usr/include/digidocpp_csharp/* WebEid.AspNetCore.Example/DigiDoc/
```

3. Publish the application with the Release configuration:

```sh
dotnet publish --configuration Release WebEid.AspNetCore.Example.sln
```

4. Update the `OriginUrl` in the `appsettings.json` to match your production environment:

```sh
sed -i 's#"OriginUrl": "https://localhost:44391"#"OriginUrl": "https://example.com"#' WebEid.AspNetCore.Example/bin/Release/net6.0/publish/appsettings.json
```

### Building the Docker image

After successfully building the application, you can create a Docker image:

```sh
docker build -t web-eid-asp-dotnet-example .
```

This command builds a Docker image named `web-eid-asp-dotnet-example` using the `Dockerfile` in the current directory.

## Running the Docker container with HTTPS support

To enable HTTPS support for the .NET application, you have two primary options:

1. Directly configure Kestrel to use HTTPS by setting up the necessary certificate information in the app's configuration files. This method is detailed in the [ASP.NET Core documentation](https://docs.microsoft.com/aspnet/core/security/enforcing-ssl).
2. Employ a reverse proxy that manages TLS termination and forwards requests to the application over HTTP. This is a common pattern in production environments due to its flexibility.
In this project, we assume the application is running behind a reverse proxy.
First, the proxy server must pass the `Host:` line from the incoming request to the proxied application and set the `X-Forwarded-*` headers to inform the application that it runs behind a reverse proxy. Here is example configuration for the Apache web server:
<Location />
ProxyPreserveHost On
ProxyPass http://localhost:8480/
ProxyPassReverse http://localhost:8480/
RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443
</Location>
Next, the .NET application must be configured to recognize and honor the `X-Forwarded-*` headers. This can be done by configuring the Forwarded Headers middleware in `Startup.cs`:
```csharp
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
```
By default, this middleware is already enabled in the application.
A Docker Compose configuration file `docker-compose.yml` is available in the `src` directory for running the Docker image `web-eid-asp-dotnet-example` on port 8480 behind a reverse proxy.
4 changes: 3 additions & 1 deletion src/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
README.md

!WebEid.AspNetCore.Example/bin/Release/net6.0/publish/
22 changes: 22 additions & 0 deletions src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# We're using .NET 6 now, but when we migrate to .NET 8 in the future, we should use chiseled images.
FROM mcr.microsoft.com/dotnet/aspnet:6.0-jammy

WORKDIR /app

COPY ria_public_key.gpg /usr/share/keyrings/ria-repository.gpg

# Add RIA repository to install the official libdigidocpp-csharp package. As each RUN commits the layer to image,
# need to chain commands and clean up in the end to keep the image small.
RUN echo "deb [signed-by=/usr/share/keyrings/ria-repository.gpg] https://installer.id.ee/media/ubuntu/ jammy main" > /etc/apt/sources.list.d/ria-repository.list && \
apt-get update && \
apt-get install -y --no-install-recommends libdigidocpp-csharp && \
apt-get clean && \
rm -rf /var/lib/apt/lists

COPY ./WebEid.AspNetCore.Example/bin/Release/net6.0/publish/ .

ENV ASPNETCORE_ENVIRONMENT=Production

EXPOSE 80

ENTRYPOINT ["dotnet", "WebEid.AspNetCore.Example.dll"]
5 changes: 3 additions & 2 deletions src/WebEid.AspNetCore.Example/Signing/SigningService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using digidoc;
Expand All @@ -12,7 +13,7 @@

public class SigningService
{
private const string FileToSign = @"wwwroot\files\example-for-signing.txt";
private static readonly string FileToSign = Path.Combine("wwwroot", "files", "example-for-signing.txt");
private readonly DigiDocConfiguration configuration;
private readonly ILogger logger;

Expand Down Expand Up @@ -40,7 +41,7 @@ public DigestDto PrepareContainer(CertificateDto data, ClaimsIdentity identity,
container.addDataFile(FileToSign, "application/octet-stream");
logger?.LogInformation("Preparing container for signing for file '{0}'", tempContainerName);
var signature =
container.prepareWebSignature(certificate.Export(X509ContentType.Cert), "BES/time-stamp");
container.prepareWebSignature(certificate.Export(X509ContentType.Cert), "time-stamp");
container.save();
return new DigestDto
{
Expand Down
14 changes: 13 additions & 1 deletion src/WebEid.AspNetCore.Example/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace WebEid.AspNetCore.Example
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
Expand Down Expand Up @@ -102,6 +103,15 @@ public void ConfigureServices(IServiceCollection services)
services.AddSingleton<IChallengeNonceGenerator, ChallengeNonceGenerator>();

services.AddAntiforgery();

// Add support for running behind a TLS terminating proxy.
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
// Only use this if you're behind a known proxy:
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
}

private static Uri GetOriginUrl(IConfiguration configuration)
Expand All @@ -121,14 +131,16 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
// Add support for running behind a TLS terminating proxy.
app.UseForwardedHeaders();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
Expand Down
8 changes: 8 additions & 0 deletions src/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '2'
services:
web-eid-asp-dotnet-example:
image: registry.gitlab.com/web-eid/service/web-eid-authentication-token-validation-dotnet/web-eid-asp-dotnet-example
restart: always
ports:
- '127.0.0.1:8480:80'

Binary file added src/ria_public_key.gpg
Binary file not shown.

0 comments on commit c3f1417

Please sign in to comment.