From 50688d6a1894ab0454ab0dbb0e046cecf52121a0 Mon Sep 17 00:00:00 2001 From: miloschwartz Date: Tue, 20 Oct 2026 10:50:18 -0400 Subject: [PATCH] add public resource mtls --- .../access-control/forwarded-headers.mdx | 4 ++ content/docs/manage/access-control/mtls.mdx | 37 +++++++++++++++++++ .../resources/public/authentication.mdx | 8 ++++ .../resources/public/resource-policies.mdx | 1 + lib/navigation.json | 1 + 5 files changed, 51 insertions(+) create mode 100644 content/docs/manage/access-control/mtls.mdx diff --git a/content/docs/manage/access-control/forwarded-headers.mdx b/content/docs/manage/access-control/forwarded-headers.mdx index 89457c7..082cd16 100644 --- a/content/docs/manage/access-control/forwarded-headers.mdx +++ b/content/docs/manage/access-control/forwarded-headers.mdx @@ -53,6 +53,10 @@ These authentication methods do not provide user identity information: +## Client Certificate (mTLS) + +When [mTLS](/manage/access-control/mtls) is enabled on a public resource, verified client certificate details are forwarded in `X-Forwarded-Tls-Client-Cert-Info` (subject, issuer, serial number, validity, and SANs). That header is independent of the `Remote-*` identity headers above and is available whenever the TLS handshake succeeds with a trusted client certificate. + ## AI Gateway [AI Gateway](/manage/ai/overview) resources forward the same `Remote-User`, `Remote-Email`, `Remote-Name`, and `Remote-Role` headers to the upstream model API when Pangolin knows the user: diff --git a/content/docs/manage/access-control/mtls.mdx b/content/docs/manage/access-control/mtls.mdx new file mode 100644 index 0000000..14f2536 --- /dev/null +++ b/content/docs/manage/access-control/mtls.mdx @@ -0,0 +1,37 @@ +--- +title: "Client Certificate (mTLS)" +description: "Require a trusted client certificate before any other public resource authentication" +--- + +Client certificate (mTLS) authentication requires browsers and API clients to present a certificate signed by a CA you trust. It is configured on public resources alongside PIN, passcode, email OTP, and other auth methods, but it is enforced earlier: during the TLS handshake, before those methods run. + +Pangolin does not issue or host client certificates. You bring your own CA and distribute client certificates to the devices or clients that should connect. + + +This is separate from [Pangolin Site mTLS](/manage/sites/configure-site#mtls-authentication), which authenticates a Newt site to the control plane. + + +## Requirements + +- The resource must be an **HTTPS** public resource with **SSL** enabled +- At least one trusted **CA public certificate** must be uploaded before you can require client certificates + +## Configure mTLS + +On the resource (or a [resource policy](/manage/resources/public/resource-policies)): + +1. Open **Authentication** and enable **Client Certificate (mTLS)** under Other Methods. +2. Upload one or more trusted CA certificates (PEM, `.pem`, `.crt`, or `.cer`). Bundles are supported. Upload public CA certificates only—never a private key. + +You can add up to 20 trusted CA certificates. Removing the last CA turns mTLS off automatically. + +## How It Behaves + +- When mTLS is required, clients without a valid certificate fail the TLS handshake. Browsers show a connection error, not the Pangolin login page. +- There is no optional mode: if enabled, a valid client certificate is always required. +- After the handshake succeeds, other configured auth methods still apply (SSO, PIN, passcode, email OTP, header auth, shareable links, and access rules). +- Access rules cannot skip mTLS. Bypass-auth rules only skip later authentication stages. + +## Backend Certificate Details + +When a client connects successfully, Pangolin forwards verified certificate details to your backend in the `X-Forwarded-Tls-Client-Cert-Info` header (subject, issuer, serial number, validity, and SANs). This is separate from the identity headers documented in [Forwarded Headers](/manage/access-control/forwarded-headers). diff --git a/content/docs/manage/resources/public/authentication.mdx b/content/docs/manage/resources/public/authentication.mdx index e472c79..2400233 100644 --- a/content/docs/manage/resources/public/authentication.mdx +++ b/content/docs/manage/resources/public/authentication.mdx @@ -41,6 +41,14 @@ You can also pass access tokens via query params or headers to resources to enab First whitelist specific emails or wildcards, like `*@.example.com`. When users visit the resource, they will be prompted to enter an email. If the email they enter is on the whitelist, a temporary one time passcode will be sent to their email. Users can then enter this OTP to gain access to the resource. +## Client Certificate (mTLS) + +Require clients to present a certificate signed by a CA you trust. mTLS is configured alongside the other methods above, but it runs first—during the TLS handshake, before PIN, SSO, email OTP, or any other auth. Clients without a valid certificate never reach the login page; the connection fails instead. + +The resource must use HTTP with SSL enabled. Upload trusted CA public certificates, then enable **Require client certificate**. Pangolin does not issue client certificates for you. + +[Read more about Client Certificate (mTLS)](/manage/access-control/mtls). + ## Rules to Access or Deny Define ranked rules to either block or allow access from specific IPs, geolocation, URL paths, and more. diff --git a/content/docs/manage/resources/public/resource-policies.mdx b/content/docs/manage/resources/public/resource-policies.mdx index dfcd8e9..f65db38 100644 --- a/content/docs/manage/resources/public/resource-policies.mdx +++ b/content/docs/manage/resources/public/resource-policies.mdx @@ -40,6 +40,7 @@ A resource policy holds the same settings you configure on a public resource's a - PIN and passcode - User and role assignments - Shareable links, access tokens, and email OTP +- Client certificate (mTLS) **Access rules** diff --git a/lib/navigation.json b/lib/navigation.json index 8b46d34..75d3c44 100644 --- a/lib/navigation.json +++ b/lib/navigation.json @@ -185,6 +185,7 @@ "manage/asnblocking", "manage/access-control/links", "manage/access-control/approvals", + "manage/access-control/mtls", "manage/access-control/forwarded-headers", "manage/access-control/login-page" ]