From 9136219106c6dec720d5ac901282978ba5205ac4 Mon Sep 17 00:00:00 2001 From: Tim Hess Date: Tue, 1 Jul 2025 16:02:14 -0500 Subject: [PATCH 1/4] Document reverse proxy support enabled by the Cloud Foundry configuration provider --- .vscode/settings.json | 1 + .../configuration/cloud-foundry-provider.md | 20 +++++++++++++++++++ docs/docs/v4/security/certificate.md | 6 +++++- docs/docs/v4/security/jwt-bearer.md | 5 ++--- docs/docs/v4/security/sso-open-id.md | 5 ++--- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a1fff093..4428a17d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "appsettings", "Blazor", "docfx", + "Gorouter", "LastExitCode", "steeltoe", "tanzu" diff --git a/docs/docs/v4/configuration/cloud-foundry-provider.md b/docs/docs/v4/configuration/cloud-foundry-provider.md index d6c3e2e2..3586b5b4 100644 --- a/docs/docs/v4/configuration/cloud-foundry-provider.md +++ b/docs/docs/v4/configuration/cloud-foundry-provider.md @@ -118,3 +118,23 @@ public class HomeController( } } ``` + +### Reverse‑Proxy and Forwarded Headers Support + +Cloud Foundry places applications behind a reverse‑proxy (the **Gorouter**), which forwards client IP, protocol, and other metadata using HTTP headers like `X‑Forwarded‑For` and `X‑Forwarded‑Proto`. + +When an application that uses the Cloud Foundry configuration provider is running on Cloud Foundry, the ASP.NET Core switch `ASPNETCORE_FORWARDEDHEADERS_ENABLED` is set to `true` so that ASP.NET Core's Forwarded Headers Middleware is enabled and configured to trust the proxy headers found in Cloud Foundry environments. + +Review the [documentation for configuration ASP.NET Core to work with a reverse proxy](https://learn.microsoft.com/aspnet/core/host-and-deploy/proxy-load-balancer#forward-the-scheme-for-linux-and-non-iis-reverse-proxies) to learn more. + +#### Customizing ForwardedHeadersOptions + +`ForwardedHeadersOptions` is configured like any other class that is accessed with `IOptions`, so you may configure them in `Program.cs`: + +```csharp +builder.Services.Configure(options => +{ + options.ForwardedHeaders |= ForwardedHeaders.XForwardedHost; + options.KnownProxies.Add(IPAddress.Parse("10.0.0.5")); // your internal proxy +}); +``` diff --git a/docs/docs/v4/security/certificate.md b/docs/docs/v4/security/certificate.md index 112887a7..e03624af 100644 --- a/docs/docs/v4/security/certificate.md +++ b/docs/docs/v4/security/certificate.md @@ -101,10 +101,14 @@ To activate certificate-based authorization in the request pipeline, use the `Us ```csharp var app = builder.Build(); -// Steeltoe: Use certificate and header forwarding along with ASP.NET Core Authentication and Authorization middleware +// Steeltoe: Use certificate forwarding along with ASP.NET Core Authentication and Authorization middleware app.UseCertificateAuthorization(); ``` +> [!NOTE] +> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> [Reverse-proxy support is automatically configured by the configuration provider for Cloud Foundry](../configuration/cloud-foundry-provider.md#reverseproxy-and-forwarded-headers-support). + ### Securing Endpoints > [!NOTE] diff --git a/docs/docs/v4/security/jwt-bearer.md b/docs/docs/v4/security/jwt-bearer.md index 72f0a512..54ad8077 100644 --- a/docs/docs/v4/security/jwt-bearer.md +++ b/docs/docs/v4/security/jwt-bearer.md @@ -112,8 +112,6 @@ Activate authentication and authorization services _after_ routing services, but ```csharp var app = builder.Build(); -app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedProto }); - app.UseRouting(); app.UseAuthentication(); @@ -125,7 +123,8 @@ app.Run(); ``` > [!NOTE] -> In this sample code, `app.UseForwardedHeaders` is used so that any links generated within the application are compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> [Reverse-proxy support is automatically configured by the configuration provider for Cloud Foundry](../configuration/cloud-foundry-provider.md#reverseproxy-and-forwarded-headers-support). ### Securing Endpoints diff --git a/docs/docs/v4/security/sso-open-id.md b/docs/docs/v4/security/sso-open-id.md index 101b7938..38fbf1cf 100644 --- a/docs/docs/v4/security/sso-open-id.md +++ b/docs/docs/v4/security/sso-open-id.md @@ -126,8 +126,6 @@ using Microsoft.AspNetCore.HttpOverrides; var app = builder.Build(); -app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedProto }); - app.UseRouting(); app.UseAuthentication(); @@ -139,7 +137,8 @@ app.Run(); ``` > [!NOTE] -> In the sample code above, `app.UseForwardedHeaders` is used so that any links generated within the application are compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> [Reverse-proxy support is automatically configured by the configuration provider for Cloud Foundry](../configuration/cloud-foundry-provider.md#reverseproxy-and-forwarded-headers-support). ### Securing Endpoints From bc644d097598713053504cbfe5910a4bd5f26d68 Mon Sep 17 00:00:00 2001 From: Tim Hess Date: Tue, 1 Jul 2025 16:41:26 -0500 Subject: [PATCH 2/4] Describe how to get and add AdditionalChainCertificates for cross-platform certificate auth on Cloud Foundry --- docs/docs/v4/security/certificate.md | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/docs/v4/security/certificate.md b/docs/docs/v4/security/certificate.md index e03624af..eee3dd6c 100644 --- a/docs/docs/v4/security/certificate.md +++ b/docs/docs/v4/security/certificate.md @@ -14,6 +14,7 @@ To use this provider, the following steps are required: 1. Add and use the security provider in the application. 1. Secure your endpoints. 1. Attach certificate to requests to secured endpoints. +1. (Optional) Add support for additional intermediate certificate authorities. ### Add NuGet Reference @@ -178,3 +179,41 @@ builder.Services.AddHttpClient().AddAppInstanceIdentityCertifi ``` This method has an overload that changes the name of the HTTP header used to pass the certificate. For example: `.AddAppInstanceIdentityCertificate("X-Custom-Certificate-Header")`. + +### Customizing CertificateAuthenticationOptions + +In some scenarios - particularly when running applications across Linux and Windows cells in Cloud Foundry - you may encounter issues where instance identity certificates are not trusted, even though they are properly issued. +This usually happens because the identity certificates are signed by different intermediate certificates depending on the operating system. + +If the intermediate certificate from one environment is not included in the trust store of the other, authentication can fail with errors such as: + +```text +Certificate validation failed... NotSignatureValid The signature of the certificate cannot be verified. +``` + +To resolve this, you can manually extract the intermediate certificate from a trusted identity certificate, export it to a .crt file, and then configure `CertificateAuthenticationOptions` to include it. + +1. Extract the identity certificate: + + ```shell + cf ssh your-app-name + cat /etc/cf-instance-credentials/instance.crt + ``` + +1. Copy everything from the second `-----BEGIN CERTIFICATE-----` to the ending `-----END CERTIFICATE-----` and save it all in a separate file (such as `intermediate.crt`) + +1. Now that you have the intermediate certificate as its own .crt file, configure CertificateAuthenticationOptions to include it during the certificate chain validation: + + ```csharp + using System.Security.Cryptography.X509Certificates; + using Microsoft.AspNetCore.Authentication; + + builder.Services + .AddAuthentication() + .AddCertificate( + options => + { + X509Certificate2 certificate = new X509Certificate2("intermediate.crt"); + options.AdditionalChainCertificates.Add(certificate); + }); + ``` From b07518397d807c38738e6b021dac09fc8554aaa5 Mon Sep 17 00:00:00 2001 From: Tim Hess Date: Wed, 2 Jul 2025 07:47:14 -0500 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Bart Koelman <104792814+bart-vmware@users.noreply.github.com> --- .../v4/configuration/cloud-foundry-provider.md | 4 ++-- docs/docs/v4/security/certificate.md | 17 ++++++++--------- docs/docs/v4/security/sso-open-id.md | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/docs/v4/configuration/cloud-foundry-provider.md b/docs/docs/v4/configuration/cloud-foundry-provider.md index 3586b5b4..1a9208c8 100644 --- a/docs/docs/v4/configuration/cloud-foundry-provider.md +++ b/docs/docs/v4/configuration/cloud-foundry-provider.md @@ -123,13 +123,13 @@ public class HomeController( Cloud Foundry places applications behind a reverse‑proxy (the **Gorouter**), which forwards client IP, protocol, and other metadata using HTTP headers like `X‑Forwarded‑For` and `X‑Forwarded‑Proto`. -When an application that uses the Cloud Foundry configuration provider is running on Cloud Foundry, the ASP.NET Core switch `ASPNETCORE_FORWARDEDHEADERS_ENABLED` is set to `true` so that ASP.NET Core's Forwarded Headers Middleware is enabled and configured to trust the proxy headers found in Cloud Foundry environments. +When an application that uses the Cloud Foundry configuration provider is running on Cloud Foundry, it sets the ASP.NET Core `ASPNETCORE_FORWARDEDHEADERS_ENABLED` switch to `true`, so that ASP.NET Core's Forwarded Headers Middleware is enabled and configured to trust the proxy headers found in Cloud Foundry environments. Review the [documentation for configuration ASP.NET Core to work with a reverse proxy](https://learn.microsoft.com/aspnet/core/host-and-deploy/proxy-load-balancer#forward-the-scheme-for-linux-and-non-iis-reverse-proxies) to learn more. #### Customizing ForwardedHeadersOptions -`ForwardedHeadersOptions` is configured like any other class that is accessed with `IOptions`, so you may configure them in `Program.cs`: +`ForwardedHeadersOptions` is configured using the [Options Pattern](https://learn.microsoft.com/aspnet/core/fundamentals/configuration/options), for example, in `Program.cs`: ```csharp builder.Services.Configure(options => diff --git a/docs/docs/v4/security/certificate.md b/docs/docs/v4/security/certificate.md index eee3dd6c..4f323659 100644 --- a/docs/docs/v4/security/certificate.md +++ b/docs/docs/v4/security/certificate.md @@ -107,7 +107,7 @@ app.UseCertificateAuthorization(); ``` > [!NOTE] -> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running on Cloud Foundry. > [Reverse-proxy support is automatically configured by the configuration provider for Cloud Foundry](../configuration/cloud-foundry-provider.md#reverseproxy-and-forwarded-headers-support). ### Securing Endpoints @@ -183,9 +183,9 @@ This method has an overload that changes the name of the HTTP header used to pas ### Customizing CertificateAuthenticationOptions In some scenarios - particularly when running applications across Linux and Windows cells in Cloud Foundry - you may encounter issues where instance identity certificates are not trusted, even though they are properly issued. -This usually happens because the identity certificates are signed by different intermediate certificates depending on the operating system. +This usually happens because the identity certificates are signed by different intermediate certificates, depending on the operating system. -If the intermediate certificate from one environment is not included in the trust store of the other, authentication can fail with errors such as: +If the intermediate certificate from one environment is not included in the trust store of the other, authentication can fail with errors, such as: ```text Certificate validation failed... NotSignatureValid The signature of the certificate cannot be verified. @@ -210,10 +210,9 @@ To resolve this, you can manually extract the intermediate certificate from a tr builder.Services .AddAuthentication() - .AddCertificate( - options => - { - X509Certificate2 certificate = new X509Certificate2("intermediate.crt"); - options.AdditionalChainCertificates.Add(certificate); - }); + .AddCertificate(options => + { + X509Certificate2 certificate = new X509Certificate2("intermediate.crt"); + options.AdditionalChainCertificates.Add(certificate); + }); ``` diff --git a/docs/docs/v4/security/sso-open-id.md b/docs/docs/v4/security/sso-open-id.md index 38fbf1cf..c6448b8c 100644 --- a/docs/docs/v4/security/sso-open-id.md +++ b/docs/docs/v4/security/sso-open-id.md @@ -137,7 +137,7 @@ app.Run(); ``` > [!NOTE] -> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running in Cloud Foundry. +> This feature requires the application to be compatible with reverse-proxy scenarios, such as when running on Cloud Foundry. > [Reverse-proxy support is automatically configured by the configuration provider for Cloud Foundry](../configuration/cloud-foundry-provider.md#reverseproxy-and-forwarded-headers-support). ### Securing Endpoints From 138d4fad50f12b05f2c748247b0b23aac6998a49 Mon Sep 17 00:00:00 2001 From: Tim Hess Date: Wed, 2 Jul 2025 11:02:48 -0500 Subject: [PATCH 4/4] parentheses instead of dashes --- docs/docs/v4/security/certificate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/v4/security/certificate.md b/docs/docs/v4/security/certificate.md index 4f323659..582bdf01 100644 --- a/docs/docs/v4/security/certificate.md +++ b/docs/docs/v4/security/certificate.md @@ -182,7 +182,7 @@ This method has an overload that changes the name of the HTTP header used to pas ### Customizing CertificateAuthenticationOptions -In some scenarios - particularly when running applications across Linux and Windows cells in Cloud Foundry - you may encounter issues where instance identity certificates are not trusted, even though they are properly issued. +In some scenarios (particularly when running applications across Linux and Windows cells in Cloud Foundry), you may encounter issues where instance identity certificates are not trusted, even though they are properly issued. This usually happens because the identity certificates are signed by different intermediate certificates, depending on the operating system. If the intermediate certificate from one environment is not included in the trust store of the other, authentication can fail with errors, such as: