Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Lets Encrypt sample and article #1673

Merged
merged 8 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions docs/docfx/articles/lets-encrypt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Lets Encrypt

## Introduction
YARP can support the certificate authority [Lets Encrypt](https://letsencrypt.org/) by using the API of another ASP.NET Core project [LettuceEncrypt](https://github.com/natemcmaster/LettuceEncrypt). It allows you to set up TLS between the client and YARP with minimal configuration.

## Requirements

Add the LettuceEncrypt package dependency:
```csproj
<PackageReference Include="LettuceEncrypt" Version="1.1.2" />
```

## Configuration
There are required options for LettuceEncrypt that should be set, see the example of `appsettings.json`:

```JSON
{
"Urls": "http://*:80;https://*:443",

"Logging": { ... },

"ReverseProxy": {
"Routes": { ... },
"Clusters": { ... }
},

"LettuceEncrypt": {
// Set this to automatically accept the terms of service of your certificate authority.
// If you don't set this in config, you will need to press "y" whenever the application starts
"AcceptTermsOfService": true,

// You must specify at least one domain name
"DomainNames": [ "example.com" ],

// You must specify an email address to register with the certificate authority
"EmailAddress": "[email protected]"
}
}
```

## Update Startup

```C#
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddLettuceEncrypt();
}
}
```

For more options (i.e. saving certificates) see examples in [LettuceEncrypt doc](ttps://github.com/natemcmaster/LettuceEncrypt).

## Kestrel Endpoints

If your project is explicitly using kestrel options to configure IP addresses, ports, or HTTPS settings, you will also need to call `UseLettuceEncrypt`.

Example:

```C#
var myHostBuilder = Host.CreateDefaultBuilder(args);
myHostBuilder.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.ConfigureKestrel(kestrel =>
{
kestrel.ListenAnyIP(443, portOptions =>
{
portOptions.UseHttps(h =>
{
h.UseLettuceEncrypt(kestrel.ApplicationServices);
});
});
});
webHostBuilder.UseStartup<Startup>();
});
```

2 changes: 2 additions & 0 deletions docs/docfx/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@
href: ab-testing.md
- name: HTTP/3
href: http3.md
- name: Lets Encrypt
href: lets-encrypt.md
11 changes: 11 additions & 0 deletions reverse-proxy.sln
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PodStatusConditions", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UsingCustomResources", "src\OperatorFramework\examples\UsingCustomResources\UsingCustomResources.csproj", "{B1E26FA9-E66B-44BD-BFEB-1F412AC09BB9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReverseProxy.LetsEncrypt.Sample", "samples\ReverseProxy.LetsEncrypt.Sample\ReverseProxy.LetsEncrypt.Sample.csproj", "{AC0EF892-7D32-4EAF-BE99-3696181E889F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -442,6 +444,14 @@ Global
{B1E26FA9-E66B-44BD-BFEB-1F412AC09BB9}.Release|Any CPU.Build.0 = Release|Any CPU
{B1E26FA9-E66B-44BD-BFEB-1F412AC09BB9}.Release|x64.ActiveCfg = Release|Any CPU
{B1E26FA9-E66B-44BD-BFEB-1F412AC09BB9}.Release|x64.Build.0 = Release|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Debug|x64.ActiveCfg = Debug|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Debug|x64.Build.0 = Debug|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Release|Any CPU.Build.0 = Release|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Release|x64.ActiveCfg = Release|Any CPU
{AC0EF892-7D32-4EAF-BE99-3696181E889F}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -494,6 +504,7 @@ Global
{300457D7-2FBF-4D10-926F-46A44A517851} = {3A8C7CF8-1F32-474E-B68A-B548A3384BB4}
{76A6BC0C-6895-4763-BB0D-E3BA99C55EC5} = {300457D7-2FBF-4D10-926F-46A44A517851}
{B1E26FA9-E66B-44BD-BFEB-1F412AC09BB9} = {300457D7-2FBF-4D10-926F-46A44A517851}
{AC0EF892-7D32-4EAF-BE99-3696181E889F} = {149C61A2-D9F8-49B9-9F9B-3C953FEF53AA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {31F6924A-E427-4830-96E9-B47CEB7BFE78}
Expand Down
1 change: 1 addition & 0 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ The following samples are provided:
| [Configuration Filter](ReverseProxy.ConfigFilter.Sample) | Shows how to use extensibility to modify configuration as its loaded from the configuration file. This sample implements an indirection to enable config values to be pulled from environment variables which can be useful in a cloud environment. |
| [Metrics](ReverseProxy.Metrics.Sample) | Shows how to consume YARP telemetry. This sample collects detailed timings for the sub-operations involved in the proxy process. |
| [Using IHttpProxy Directly](ReverseProxy.Direct.Sample) | Shows how to use IHttpProxy, which performs the proxy operation, directly without using YARP's configuration, pipeline etc. |
| [Lets Encrypt](ReverseProxy.LetsEncrypt.Sample) | Shows how to use a certificate authority such as Lets Encrypt to set up TLS termination in YARP. |
| [Kubernetes Ingress](KubernetesIngress) | Shows how to use YARP as a Kubernetes ingress controller |
| [Prometheus](Prometheus) | Shows how to consume the YARP telemetry library and export metrics to external telemetry such as Prometheus |
24 changes: 24 additions & 0 deletions samples/ReverseProxy.LetsEncrypt.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;

namespace Yarp.Sample
{
public class Program
{
public static void Main(string[] args)
{
// Create a Kestrel web server, and tell it to use the Startup class
// for the service configuration
var myHostBuilder = Host.CreateDefaultBuilder(args);
myHostBuilder.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.UseStartup<Startup>();
});
var myHost = myHostBuilder.Build();
myHost.Run();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"ReverseProxy.LetsEncrypt.Sample": {
"commandName": "Project",
"launchBrowser": false,
"launchUrl": "",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
13 changes: 13 additions & 0 deletions samples/ReverseProxy.LetsEncrypt.Sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Lets Encrypt Sample

[Lets Encrypt](https://letsencrypt.org/) is a certificate authority (CA) that provides HTTPS (SSL/TLS) certificates for free. This sample shows how to add Lets Encrypt for TLS termination in YARP by integrating with [LettuceEncrypt](https://github.com/natemcmaster/LettuceEncrypt). It allows to set up TLS between the client and YARP with minimal configuration.

The sample includes the following parts:

- ### [Startup.cs](Startup.cs)
It calls `IServiceCollection.AddLettuceEncrypt` in the `ConfigureServices` method.

- ### [appsettings.json](appsettings.json)
Sets up the required options for LettuceEncrypt including:
- "DomainNames" - at least one domain name is required
- "EmailAddress" - email address must be specified to register with the certificate authority
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>net6.0;net5.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="LettuceEncrypt" Version="1.1.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ReverseProxy\Yarp.ReverseProxy.csproj" />
</ItemGroup>

</Project>
50 changes: 50 additions & 0 deletions samples/ReverseProxy.LetsEncrypt.Sample/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using LettuceEncrypt;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Yarp.Sample
{
// Sets up the ASP.NET application with the reverse proxy enabled.
public class Startup
{
public Startup(IConfiguration configuration)
{
// Default configuration comes from AppSettings.json file in project/output
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add capabilities to
// the web application via services in the DI container.
public void ConfigureServices(IServiceCollection services)
{
services.AddLettuceEncrypt();

// Add the reverse proxy capability to the server
var proxyBuilder = services.AddReverseProxy();
// Initialize the reverse proxy from the "ReverseProxy" section of configuration
proxyBuilder.LoadFromConfig(Configuration.GetSection("ReverseProxy"));
}

// This method gets called by the runtime. Use this method to configure the HTTP request
// pipeline that handles requests
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Enable endpoint routing, required for the reverse proxy
app.UseRouting();
// Register the reverse proxy routes
app.UseEndpoints(endpoints =>
{
endpoints.MapReverseProxy();
});
}
}
}
50 changes: 50 additions & 0 deletions samples/ReverseProxy.LetsEncrypt.Sample/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://*:80"
},
"Https": {
"Url": "https://*:443"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ReverseProxy": {
"Routes": {
"route1": {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}"
}
}
},
"Clusters": {
"cluster1": {
"Destinations": {
"destination1": {
"Address": "https://example.com/"
}
}
}
}
},
"LettuceEncrypt": {
// Set this to automatically accept the terms of service of your certificate authority.
// If you don't set this in config, you will need to press "y" whenever the application starts
"AcceptTermsOfService": true,

// You must specify at least one domain name
"DomainNames": [ "example.com" ],

// You must specify an email address to register with the certificate authority
"EmailAddress": "[email protected]"
}
}