This is an automated email from the ASF dual-hosted git repository.

jinwoo pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new ec974dd9ad GEODE-10561: Add Documentation for Public CA Client 
Authentication EKU Migration (#7989)
ec974dd9ad is described below

commit ec974dd9ad2c35f223187ef9914529e3195b6d0b
Author: Jinwoo Hwang <[email protected]>
AuthorDate: Mon Mar 16 13:53:08 2026 -0400

    GEODE-10561: Add Documentation for Public CA Client Authentication EKU 
Migration (#7989)
    
    * documentation
    
    * Sheila's review
    
    * GEODE-10561: fix wording in CA topology section
---
 .../source/subnavs/geode-subnav.erb                |  14 +
 ...blic_ca_client_auth_eku_mitigations.html.md.erb | 147 +++++++++
 ...hybrid_public_server_private_client.html.md.erb | 331 +++++++++++++++++++++
 .../security/ssl_internal_ca_mtls.html.md.erb      | 216 ++++++++++++++
 geode-docs/security/ssl_overview.html.md.erb       |  10 +
 .../ssl_server_only_tls_alt_auth.html.md.erb       | 301 +++++++++++++++++++
 6 files changed, 1019 insertions(+)

diff --git a/geode-book/master_middleman/source/subnavs/geode-subnav.erb 
b/geode-book/master_middleman/source/subnavs/geode-subnav.erb
index f06a8914d4..e6afa6bb95 100644
--- a/geode-book/master_middleman/source/subnavs/geode-subnav.erb
+++ b/geode-book/master_middleman/source/subnavs/geode-subnav.erb
@@ -157,6 +157,20 @@ limitations under the License.
                                     <li>
                                         <a 
href="/docs/guide/<%=vars.product_version_nodot%>/security/ssl_example.html">SSL
 Sample Implementation</a>
                                     </li>
+                                    <li class="has_submenu">
+                                        <a 
href="/docs/guide/<%=vars.product_version_nodot%>/security/public_ca_client_auth_eku_mitigations.html">Mitigating
 Public CA Client Auth EKU Changes</a>
+                                        <ul>
+                                            <li>
+                                                <a 
href="/docs/guide/<%=vars.product_version_nodot%>/security/ssl_internal_ca_mtls.html">Internal
 / Enterprise CA for mTLS</a>
+                                            </li>
+                                            <li>
+                                                <a 
href="/docs/guide/<%=vars.product_version_nodot%>/security/ssl_server_only_tls_alt_auth.html">Server-only
 TLS + Alternative Client Auth</a>
+                                            </li>
+                                            <li>
+                                                <a 
href="/docs/guide/<%=vars.product_version_nodot%>/security/ssl_hybrid_public_server_private_client.html">Hybrid:
 Public-CA Server + Private-CA Client</a>
+                                            </li>
+                                        </ul>
+                                    </li>
                                 </ul>
                             </li>
                             <li>
diff --git 
a/geode-docs/security/public_ca_client_auth_eku_mitigations.html.md.erb 
b/geode-docs/security/public_ca_client_auth_eku_mitigations.html.md.erb
new file mode 100644
index 0000000000..0831bfb651
--- /dev/null
+++ b/geode-docs/security/public_ca_client_auth_eku_mitigations.html.md.erb
@@ -0,0 +1,147 @@
+---
+title:  Mitigating Public CA Client Authentication EKU Changes
+---
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+Public Certificate Authorities (CAs) are removing or restricting issuance
+of the Client Authentication Extended Key Usage (EKU) from publicly-issued
+leaf certificates. Deployments that relied on public-CA-signed client
+certificates for mutual TLS (mTLS) client authentication must migrate to an
+alternative approach.
+
+**This guide does not apply to you if:**
+
+- Your deployment already uses an enterprise or internal CA for mTLS, **or**
+- Your deployment uses a public CA chain that includes client CA certificates
+  and those certificates are unaffected by the EKU policy change.
+
+**This guide applies to you if:**
+
+- Your deployment used public-CA-issued client certificates for mTLS, **and**
+- Those certificates no longer contain the `clientAuth` EKU, or the CA will
+  no longer issue them.
+
+## <a id="eku_background" class="no-quick-link"></a>Background
+
+<%=vars.product_name%> uses JSSE (`SSLContext`, `SSLEngine`, `SSLSocket`,
+`TrustManager`, `KeyManager`) for all TLS connections. Per-component SSL
+configuration is resolved via `SSLConfig` and `SSLConfigurationFactory`.
+Keystores and truststores are watched at runtime by 
`FileWatchingX509ExtendedKeyManager`
+and `FileWatchingX509ExtendedTrustManager`, backed by `PollingFileWatcher`,
+which reloads credential material when files change on disk without a server
+restart.
+
+When a Java TLS peer presents a certificate in a role that requires client
+authentication, the JSSE stack checks that the certificate's Extended Key Usage
+extension contains `id-kp-clientAuth` (OID 1.3.6.1.5.5.7.3.2). If that OID is
+absent, the TLS handshake fails with an authentication error. Because public 
CAs
+are ceasing to include this OID in publicly-issued leaf certificates,
+public-CA-signed client certificates can no longer be used for mTLS.
+
+## <a id="eku_decision_guide" class="no-quick-link"></a>Choosing a Mitigation
+
+Select the option that best fits your operational environment:
+
+| Scenario | Recommended option |
+|---|---|
+| You can operate or integrate with an enterprise PKI | [Internal / Enterprise 
CA for mTLS](ssl_internal_ca_mtls.html) |
+| Client certificates are impractical; you prefer credential-based auth | 
[Server-only TLS + alternative client 
authentication](ssl_server_only_tls_alt_auth.html) |
+| Servers must use a public-CA certificate (external trust) but clients need a 
controllable identity | [Hybrid: public-CA server certificates + private-CA 
client certificates](ssl_hybrid_public_server_private_client.html) |
+
+You may combine approaches: for example, running the hybrid model in production
+while temporarily using server-only TLS + credentials during a phased 
migration.
+
+## <a id="eku_common_features" class="no-quick-link"></a>Key 
<%=vars.product_name%> Features Used by All Mitigations
+
+- **Per-component SSL configuration** — `ssl-enabled-components` and associated
+  `ssl-keystore` / `ssl-truststore` properties allow independent TLS settings 
for
+  `cluster`, `server`, `locator`, `gateway`, `jmx`, and `web` components.  See
+  [Configuring SSL](implementing_ssl.html).
+- **`ssl-require-authentication`** — controls whether servers require client
+  certificates during the TLS handshake.  Set to `true` for mTLS; `false` for
+  server-only TLS.
+- **File-watching keystore reload** — `FileWatchingX509ExtendedKeyManager` and
+  `FileWatchingX509ExtendedTrustManager` automatically reload keystore and
+  truststore files when they are atomically replaced on disk.  Configure by
+  pointing `ssl-keystore` / `ssl-truststore` at the watched path.
+- **Pluggable authentication** — `AuthInitialize` (client-side credential
+  injection) and `SecurityManager` (server-side enforcement) support
+  username/password, token, and custom authentication without requiring client
+  certificates.
+
+## <a id="eku_migration_checklist" class="no-quick-link"></a>Migration 
Checklist
+
+1. **Inventory** — Identify all clients, members, and locators that present a
+   public-CA-signed client certificate during TLS handshake.
+2. **Choose a mitigation** — Use the decision table above to select an approach
+   (or a phased combination).
+3. **Provision credentials** — Issue replacement certificates from an internal/
+   private CA, or configure application-layer authentication.
+4. **Update truststores** — Update server truststores to include the new CA(s)
+   before rotating client credentials to avoid handshake failures during the
+   rollout.
+5. **Deploy and verify** — Roll out the new configuration component by 
component.
+   Use `openssl s_client` and JSSE debug logging 
(`-Djavax.net.debug=ssl,handshake`)
+   to verify handshake behavior at each step.
+6. **Remove old credentials** — Once all clients have migrated, remove the
+   public-CA trust anchor from server truststores if it is no longer needed.
+
+## <a id="eku_quick_verify" class="no-quick-link"></a>Quick Verification
+
+Test that the server certificate chain and (if applicable) client certificate
+chain are seen and accepted:
+
+```bash
+# Server-only TLS verification (no client certificate required)
+openssl s_client -connect geode-server.example.com:10334 -showcerts
+
+# mTLS verification (present client cert and key)
+openssl s_client -connect geode-server.example.com:10334 \
+  -cert client.crt -key client.key \
+  -CAfile server-trust-anchor.pem -showcerts
+```
+
+Enable JSSE debug on client JVMs for detailed handshake tracing:
+
+```bash
+java -Djavax.net.debug=ssl,handshake -jar my-geode-client.jar
+```
+
+## <a id="eku_mitigation_pages" class="no-quick-link"></a>Mitigation Guides
+
+-   **[Internal / Enterprise CA for mTLS](ssl_internal_ca_mtls.html)**
+
+    Run an internal or enterprise CA (offline root + issuing intermediate, or
+    enterprise PKI automation such as HashiCorp Vault or Smallstep) to issue
+    client certificates. The internal CA is the trust anchor for client
+    authentication; public CA EKU policies are irrelevant.
+
+-   **[Server-only TLS + Alternative Client 
Authentication](ssl_server_only_tls_alt_auth.html)**
+
+    Retain TLS encryption for all connections but disable mandatory client
+    certificate authentication.  Authenticate clients at the application layer
+    using <%=vars.product_name%>'s existing `AuthInitialize` / 
`SecurityManager`
+    framework (username/password, tokens, or a custom implementation).
+
+-   **[Hybrid: Public-CA Server Certs + Private-CA Client 
Certs](ssl_hybrid_public_server_private_client.html)**
+
+    Keep server certificates signed by a public CA (preserving external trust)
+    while issuing client certificates from an internal/private CA. Server
+    truststores include the private CA; client truststores use the public CA
+    (or the system trust store) for server certificate validation.
diff --git 
a/geode-docs/security/ssl_hybrid_public_server_private_client.html.md.erb 
b/geode-docs/security/ssl_hybrid_public_server_private_client.html.md.erb
new file mode 100644
index 0000000000..5c16121b8f
--- /dev/null
+++ b/geode-docs/security/ssl_hybrid_public_server_private_client.html.md.erb
@@ -0,0 +1,331 @@
+---
+title:  Hybrid TLS — Public-CA Server Certs with Private-CA Client Certs
+---
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+This page is part of the
+[Public CA Client Authentication EKU Mitigation 
guide](public_ca_client_auth_eku_mitigations.html).
+It describes a hybrid model in which <%=vars.product_name%> server certificates
+are issued by a public CA (preserving external trust) while client certificates
+are issued by an internal or private CA (preserving control over `clientAuth` 
EKU
+and certificate lifecycle).
+
+## <a id="hyb_summary" class="no-quick-link"></a>Summary
+
+**For Client/Server Topology:**
+
+| Certificate role | Issued by |
+|---|---|
+| Server certificate (servers / locators present to clients) | Public CA |
+| Peer-to-peer certificates (servers / locators authenticate to each other) | 
Public CA |
+| Client certificate (clients present to servers) | Internal / private CA |
+
+**For Peer-to-Peer (P2P) Topology:**
+
+| Certificate role | Issued by |
+|---|---|
+| Peer certificate (peers authenticate to each other) | Public CA |
+| Client certificate (clients present to peers, if applicable) | Internal / 
private CA |
+
+**Why this model:**
+
+- Servers and peers are reachable from the public internet or from clients that
+  trust public CAs — keeping server/peer certificates public-CA-issued avoids 
distributing
+  a custom root to all clients.
+- Servers and peers use public-CA-issued certificates to authenticate to each 
other
+  during cluster formation and peer-to-peer communication.
+- Clients are controlled endpoints (application services, internal consumers) —
+  issuing their certificates from an internal CA provides full control over the
+  `clientAuth` EKU, certificate lifetime, and revocation.
+- Public CA EKU policy changes for client certificates are irrelevant because
+  client certificates never come from the public CA.
+
+**When to choose this option:**
+
+- Your server endpoints are externally visible and must be trusted by external
+  clients using the public trust store.
+- You can operate or integrate with an internal CA for client certificate
+  issuance.
+- You want to retain full mTLS (mutual certificate authentication) rather than
+  switching to application-layer credential auth.
+
+## <a id="hyb_architecture" class="no-quick-link"></a>Architecture
+
+**For Client/Server Topology:**
+
+```
+                 Public CA trust chain
+                 (server certificate)
+  Client ──────────────────────────────▶ Server
+         ◀────────────────────────────── Server
+         validates server certificate via
+         public CA / system trust store
+
+                 Private CA trust chain
+                 (client cert)
+  Client ──────────────────────────────▶ Server
+                                          validates client certificate via
+                                          server truststore containing
+                                          private CA certificate
+
+```
+
+**For Peer-to-Peer Topology:**
+
+```
+                 Public CA trust chain
+                 (peer-to-peer)
+  Peer ◀──────────────────────────────▶ Peer
+       Each peer uses public-CA-issued certificate
+       to authenticate to other peers;
+       validation via public CA in peer truststore
+
+                 Private CA trust chain
+                 (client-to-peer, if accepting clients)
+  Client ──────────────────────────────▶ Peer
+                                          validates client certificate via
+                                          peer truststore containing
+                                          private CA certificate
+```
+
+**Key trust relationships:**
+
+- **Server keystore** — contains the public-CA-issued server leaf certificate 
and
+  its private key (and intermediate chain).
+- **Server truststore** — contains **both** the public CA (for validating other
+  servers/locators in peer-to-peer communication) **and** the private/internal 
CA
+  certificate(s) (for validating client certificates during the mTLS 
handshake).
+- **Peer keystore** (P2P topology) — contains the public-CA-issued peer 
certificate
+  and its private key (for peer-to-peer authentication).
+- **Peer truststore** (P2P topology) — contains **both** the public CA (for 
validating
+  other peers) **and** the private CA (for validating client certificates if 
the peer
+  accepts client connections).
+- **Client keystore** — contains the private-CA-issued client leaf certificate
+  and its private key.
+- **Client truststore** — contains the public CA root (or relies on the JVM
+  system trust store) to validate the server certificate.
+
+## <a id="hyb_prerequisites" class="no-quick-link"></a>Prerequisites
+
+- A server certificate chain issued by a public CA, valid for the server's
+  hostnames (DNS SANs).  Obtain this from your public CA provider.
+- An internal/private CA capable of issuing client leaf certificates with the
+  `clientAuth` EKU.  Options include HashiCorp Vault PKI, Smallstep `step-ca`,
+  Active Directory Certificate Services, or a self-managed OpenSSL CA.
+- Secure tooling to distribute keystores and truststores to servers and 
clients.
+
+## <a id="hyb_step_by_step" class="no-quick-link"></a>Step-by-Step 
Configuration
+
+### Step 1 — Prepare the server keystore (public CA)
+
+Obtain a server certificate from a public CA for your <%=vars.product_name%> 
server
+hostnames. **Ensure the server certificate includes the `serverAuth` Extended 
Key
+Usage and a `subjectAltName` (SAN) field with the server's DNS names** for 
hostname
+verification. Convert the certificate and private key into a Java keystore 
(PKCS12
+or JKS format). See [SSL Sample Implementation](ssl_example.html) for keystore
+preparation details.
+
+### Step 2 — Prepare the server truststore (both CAs)
+
+Import **both** CA certificates into the server truststore:
+
+1. Import your internal/private CA certificate(s) so servers can validate 
client
+   certificates issued by your internal CA.
+2. Import the public CA certificate(s) so servers can validate other servers 
and
+   locators during peer-to-peer cluster communication.
+
+If your <%=vars.product_name%> cluster uses SSL for peer-to-peer communication
+(e.g., `ssl-enabled-components=all` or includes `cluster`/`locator` 
components),
+servers must trust the public CA that issued other members' certificates.
+
+### Step 3 — Issue client certificates from the internal CA
+
+Use your internal PKI to issue client certificates. **Ensure the client 
certificates
+include the `clientAuth` Extended Key Usage** (required for client 
authentication
+in mTLS). Without this EKU, the server will reject the client certificate with 
a
+`certificate_unknown` TLS alert. Create a client keystore containing the client
+private key and certificate chain.
+
+### Step 4 — Prepare the client truststore (public CA for server validation)
+
+Clients must be able to validate the server's public-CA-issued certificate.
+In most cases the JVM system trust store already contains public CA roots and
+no additional configuration is needed. If you need to use a custom truststore,
+import the public CA root certificate(s).
+
+### Step 5 — Configure <%=vars.product_name%> server / locator
+
+``` pre
+ssl-enabled-components=all
+
+# Server keystore: public-CA-issued server certificate
+ssl-keystore=/etc/geode/server-keystore.jks
+ssl-keystore-password=<password>
+ssl-keystore-type=JKS
+
+# Server truststore: BOTH public CA (for peer-to-peer) and private CA (for 
clients)
+ssl-truststore=/etc/geode/server-truststore.jks
+ssl-truststore-password=<password>
+ssl-truststore-type=JKS
+
+# Require client certificates in the TLS handshake
+ssl-require-authentication=true
+
+# Validate server hostname from the client side
+ssl-endpoint-identification-enabled=true
+```
+
+### Step 6 — Configure <%=vars.product_name%> client
+
+``` pre
+ssl-enabled-components=all
+
+# Client keystore: private-CA-issued client certificate
+ssl-keystore=/etc/geode/client-keystore.jks
+ssl-keystore-password=<password>
+ssl-keystore-type=JKS
+
+# Client truststore: public CA root (validates server certificate)
+# If using system trust store, ssl-use-default-context=true may be sufficient
+ssl-truststore=/etc/geode/client-truststore.jks
+ssl-truststore-password=<password>
+ssl-truststore-type=JKS
+
+# Require server certificate authentication
+ssl-require-authentication=true
+
+ssl-endpoint-identification-enabled=true
+```
+
+## <a id="hyb_p2p_topology" class="no-quick-link"></a>P2P Topology 
Configuration
+
+In a peer-to-peer (P2P) topology, all members are peers with equal standing.
+Each peer acts as both a server (for other peers and clients) and a client 
(when
+connecting to other peers). This requires careful certificate and trust store
+configuration.
+
+**Key P2P requirements:**
+
+- Each peer presents a **public-CA-issued certificate** for peer-to-peer 
authentication
+  (so peers can authenticate each other using the public CA trust chain).
+- Each peer's truststore must contain **both** CAs:
+  - The **public CA** (to validate certificates from other peers during cluster
+    formation and ongoing peer-to-peer communication).
+  - The **private CA** (to validate client certificates if the peer also 
accepts
+    client connections).
+
+**Example P2P member configuration:**
+
+``` pre
+ssl-enabled-components=all
+
+# Peer keystore: public-CA-issued certificate (for peer-to-peer auth)
+ssl-keystore=/etc/geode/peer-keystore.jks
+ssl-keystore-password=<password>
+ssl-keystore-type=JKS
+
+# Peer truststore: BOTH public CA (other peers) and private CA (clients)
+ssl-truststore=/etc/geode/peer-truststore.jks
+ssl-truststore-password=<password>
+ssl-truststore-type=JKS
+
+ssl-require-authentication=true
+ssl-endpoint-identification-enabled=true
+```
+
+**Client configuration for P2P clusters:**
+
+If clients connect to the P2P cluster, their configuration remains the same as
+in the client/server topology described above (private-CA-issued client 
keystore,
+public-CA truststore for server validation).
+
+## <a id="hyb_rotation" class="no-quick-link"></a>Certificate Rotation and 
Hot-Reload
+
+<%=vars.product_name%>'s `FileWatchingX509ExtendedKeyManager` and
+`FileWatchingX509ExtendedTrustManager` monitor the configured keystore and
+truststore paths and reload them when files change on disk — no restart 
required.
+
+**Rotation workflow:**
+
+| What rotates | Procedure |
+|---|---|
+| Server certificate (public CA renewal) | Write new `server-keystore.jks` 
atomically; `FileWatchingX509ExtendedKeyManager` reloads it |
+| Client certificate (private CA rotation) | Automation writes new 
`client.p12` / JKS atomically; `FileWatchingX509ExtendedKeyManager` reloads it |
+| Private CA rollover | Import new private CA certificate into 
`server-truststore.jks` before client certificates rotate; do a rolling 
truststore push or atomic file replacement |
+| Public CA root renewal | Update `client-truststore.jks` on all clients and 
`server-truststore.jks` on all servers/locators (or rely on JVM trust store 
update) |
+
+Write files atomically — create a temp file, write it fully, then `rename()` it
+into the watched path so the watcher reads a complete file.
+
+## <a id="hyb_verification" class="no-quick-link"></a>Verification and 
Troubleshooting
+
+**Enable JSSE debug logging** to diagnose SSL/TLS handshake issues:
+
+```
+-Djavax.net.debug=ssl,handshake
+```
+
+**Common issues:**
+
+| Symptom | Likely cause |
+|---|---|
+| Server handshake fails: `PKIX path building failed` | Server truststore does 
not include the private CA that signed the client certificate |
+| Client handshake fails: `PKIX path building failed` | Client truststore does 
not include the public CA that signed the server certificate |
+| Peer-to-peer handshake fails: `PKIX path building failed` | 
Server/locator/peer truststore missing public CA needed to validate other 
cluster members |
+| `certificate_unknown` TLS alert from server | Client certificate is missing 
the `clientAuth` EKU, or is not trusted — verify private CA import into server 
truststore and EKU presence |
+| `certificate_unknown` TLS alert during P2P handshake | Peer certificate is 
missing the `serverAuth` EKU, or the peer's public CA is not trusted — verify 
public CA import into peer truststore and EKU presence |
+| `No subject alternative names` | Server or peer certificate does not include 
a DNS SAN matching the hostname used by the connecting party |
+
+## <a id="hyb_security_notes" class="no-quick-link"></a>Security Considerations
+
+- The hybrid model splits trust roots: public CA governs server identity;
+  private CA governs client identity.  Compromise of one does not directly
+  compromise the other.
+- Protect the private CA private key carefully.  Prefer to use an offline root 
+ online
+  issuing intermediate topology.  Consider a Hardware Security Module (HSM) 
for the issuing intermediate.
+- Keep client certificate lifetimes short (days to weeks) and automate renewal.
+- **Verify certificate Extended Key Usage (EKU) requirements:**
+  * Server certificates **must** include the `serverAuth` EKU.
+  * Client certificates **must** include the `clientAuth` EKU.
+  * Peer certificates (P2P topology) **must** include the `serverAuth` EKU for
+    peer-to-peer authentication.
+  * Java JSSE enforces EKU checking by default and will reject certificates
+    without the appropriate EKU with a `certificate_unknown` alert.
+- **Peer-to-peer authentication considerations:**
+  * In client/server topology, servers and locators use public-CA-issued
+    certificates to authenticate to each other during cluster formation and
+    peer-to-peer communication. The server truststore must contain both the
+    public CA (for peer validation) and the private CA (for client validation).
+  * In P2P topology, all peers use public-CA-issued certificates to
+    authenticate to each other. Each peer's truststore must contain both the
+    public CA (for peer validation) and the private CA (for client validation
+    if the peer accepts client connections).
+
+## <a id="hyb_references" class="no-quick-link"></a>References
+
+- [Configuring SSL](implementing_ssl.html) — complete property reference
+- [Internal / Enterprise CA for mTLS](ssl_internal_ca_mtls.html) — detailed
+  internal-CA set-up guidance
+- [Public CA Client Authentication EKU 
Mitigations](public_ca_client_auth_eku_mitigations.html) — overview and other 
mitigation options
+- `SSLConfig` and `SSLConfigurationFactory`:
+  `geode-core/src/main/java/org/apache/geode/internal/net/SSLConfig.java`
+- `FileWatchingX509ExtendedKeyManager`:
+  
`geode-core/src/main/java/org/apache/geode/internal/net/filewatch/FileWatchingX509ExtendedKeyManager.java`
+- `SocketCreator`:
+  `geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java`
diff --git a/geode-docs/security/ssl_internal_ca_mtls.html.md.erb 
b/geode-docs/security/ssl_internal_ca_mtls.html.md.erb
new file mode 100644
index 0000000000..114b12ab06
--- /dev/null
+++ b/geode-docs/security/ssl_internal_ca_mtls.html.md.erb
@@ -0,0 +1,216 @@
+---
+title:  Internal / Enterprise CA for mTLS
+---
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+This page is part of the
+[Public CA Client Authentication EKU Mitigation 
guide](public_ca_client_auth_eku_mitigations.html).
+It describes how to use an internal or enterprise Certificate Authority (CA) to
+issue client certificates so that <%=vars.product_name%> mutual TLS (mTLS) 
continues
+to work after public CAs cease including the `clientAuth` EKU in 
publicly-issued
+leaf certificates.
+
+## <a id="ica_summary" class="no-quick-link"></a>Summary
+
+Operate an internal or enterprise CA to issue client certificates (and 
optionally
+server certificates) for <%=vars.product_name%> mTLS.  This removes dependency 
on
+public CA EKU policies, centralizes client identity issuance, and enables
+fine-grained lifecycle control (rotation, short-lived certificates, automated
+enrollment).
+
+**When to choose this option:**
+
+- You can operate or integrate with an internal PKI (self-managed CA, HashiCorp
+  Vault PKI, Smallstep, Active Directory Certificate Services, or similar).
+- You want strong, certificate-based mutual authentication between clients and
+  servers with full lifecycle control.
+
+## <a id="ica_topology" class="no-quick-link"></a>Recommended CA Topology
+
+- **Offline root CA** — kept in air-gapped or cold storage; used only to sign
+  intermediate CA certificates.
+- **Online issuing intermediate CA** — used to sign leaf certificates for 
servers
+  and clients.  In the event the intermediate is compromised, only it (not the
+  root) needs to be rotated.
+- Use separate issuing CAs per environment (production, staging, development) 
to
+  prevent cross-environment trust leakage.
+- Enforce short certificate lifetimes for client leaf certificates 
(recommended:
+  1–30 days) to minimise the impact of compromise and to avoid CRL/OCSP
+  complexity. Short-lived certificates with automation provide:
+  * Reduced compromise windows (compromised certificates expire quickly)
+  * Elimination of manual coordination for renewals
+  * Zero-downtime operations via <%=vars.product_name%>'s file-watching
+    credential managers
+  * Consistent security posture through automated enforcement of required
+    EKUs and extensions
+
+## <a id="ica_cert_issuance" class="no-quick-link"></a>Certificate Issuance
+
+Use your internal PKI tools (OpenSSL, HashiCorp Vault, Active Directory 
Certificate
+Services, etc.) to issue certificates with your internal CA. Client 
certificates
+**must include the `clientAuth` Extended Key Usage** to function with 
<%=vars.product_name%>
+mTLS.
+
+**Key requirements:**
+
+- **Client certificates:** Must have `extendedKeyUsage=clientAuth`
+- **Server certificates:** Must have `extendedKeyUsage=serverAuth` and must 
include
+  `subjectAltName` with DNS names or IP addresses for hostname verification
+  (when `ssl-endpoint-identification-enabled=true`)
+- **Certificate chain:** Ensure leaf certificates are signed by a CA that is
+  trusted by the peer's truststore
+
+## <a id="ica_keystore_prep" class="no-quick-link"></a>Keystore and Truststore 
Preparation
+
+Prepare Java keystores (PKCS12 or JKS format) containing:
+
+- **Keystore:** Private key and certificate chain (for the component's 
identity)
+- **Truststore:** CA certificates used to validate peer certificates
+
+<%=vars.product_name%> supports PKCS12 (recommended) and JKS keystore formats.
+For detailed instructions on creating and managing keystores, see
+[SSL Sample Implementation](ssl_example.html).
+
+**Key points:**
+
+- **Server truststores:** Import your internal CA certificate(s) to validate 
client
+  certificates
+- **Client truststores:** Import CA certificate(s) to validate server 
certificates
+- **Password protection:** Use environment variables, secure vaults, or 
file-based
+  configuration with restricted permissions
+
+## <a id="ica_geode_config" class="no-quick-link"></a><%=vars.product_name%> 
Configuration
+
+**Server / locator (requires client certs from the internal CA):**
+
+``` pre
+ssl-enabled-components=all
+ssl-keystore=/etc/geode/server-keystore.jks
+ssl-keystore-password=<password>
+ssl-keystore-type=JKS
+ssl-truststore=/etc/geode/server-truststore.jks
+ssl-truststore-password=<password>
+ssl-truststore-type=JKS
+ssl-require-authentication=true
+ssl-endpoint-identification-enabled=true
+```
+
+**Client (presents an internal-CA-issued client cert):**
+
+``` pre
+ssl-enabled-components=all
+ssl-keystore=/etc/geode/client-keystore.jks
+ssl-keystore-password=<password>
+ssl-keystore-type=JKS
+ssl-truststore=/etc/geode/client-truststore.jks
+ssl-truststore-password=<password>
+ssl-truststore-type=JKS
+ssl-require-authentication=true
+ssl-endpoint-identification-enabled=true
+```
+
+The client truststore must contain the trust anchor used to verify the server's
+certificate (the public CA root if the server used a public-CA cert, or the
+internal root if the server cert was also issued by the internal CA).
+
+For component-specific keystores (different certs per role), use
+`server-ssl-keystore`, `locator-ssl-keystore`, etc.
+
+## <a id="ica_rotation" class="no-quick-link"></a>Rotation and Hot-Reload
+
+<%=vars.product_name%> ships `FileWatchingX509ExtendedKeyManager` and
+`FileWatchingX509ExtendedTrustManager`, backed by `PollingFileWatcher`, which
+monitor keystore and truststore files on disk and reload them when they change 
—
+no server restart required.
+
+**Best practices for rotation tooling:**
+
+- Write new keystore/truststore files atomically: create a temporary file, 
write
+  it, then `rename()` it into the watched path so the file watcher sees a clean
+  update.
+- Use short certificate lifetimes and automate renewal before expiry.  
Automation
+  tools such as HashiCorp Vault agent, Smallstep's `step-ca`, or custom ACME
+  clients can write renewed keystores atomically to the watched path.
+- When rotating the issuing CA, stage the new CA cert in server truststores 
before
+  rotating client certificates to avoid handshake failures during the overlap
+  window.
+
+## <a id="ica_automation" class="no-quick-link"></a>Enrollment Automation
+
+If you operate an existing enterprise PKI automation platform, integrate it
+rather than building a bespoke CA:
+
+- **HashiCorp Vault PKI**: Vault agent authenticates (using AppRole, Kubernetes
+  auth, or a token) and writes short-lived client certs atomically to
+  `/var/geode/`. `FileWatchingX509ExtendedKeyManager` picks up the rotation.
+- **Smallstep (`step-ca` / `step` CLI)**: Use `step ca certificate` to enroll 
and
+  renew client certificates; integrate with `step-sds` or a custom renewer that
+  writes PKCS12/JKS files atomically.
+- **ACME automation**: If your internal CA supports ACME, use an ACME client
+  (e.g., Certbot with a custom hook) to issue and renew client credentials.
+
+The key integration pattern in all cases:
+1. Automation authenticates to the CA.
+2. CA issues a short-lived client cert.
+3. Automation writes the keystore atomically to the watched path.
+4. `FileWatchingX509ExtendedKeyManager` reloads the credential without restart.
+
+## <a id="ica_revocation" class="no-quick-link"></a>Revocation Strategy
+
+- **Short-lived certificates (recommended):** Use 1–30 day lifetimes with
+  automated renewal.  Because certificates expire soon, CRL/OCSP infrastructure
+  is not required.
+- **CRL or OCSP (longer-lived certs):** If longer certificate lifetimes are
+  required, publish a CRL distribution point or OCSP responder as part of your
+  internal CA, and configure the JVM trust policy accordingly.
+
+## <a id="ica_verification" class="no-quick-link"></a>Verification and 
Troubleshooting
+
+**Enable JSSE debug logging** to diagnose SSL/TLS handshake issues:
+
+```
+-Djavax.net.debug=ssl,handshake
+```
+
+**Common issues:**
+
+| Symptom | Likely cause |
+|---|---|
+| `PKIX path building failed` | Truststore does not include the CA that signed 
the peer's certificate |
+| `certificate_unknown` alert | Client certificate lacks the required 
`clientAuth` Extended Key Usage, or server certificate lacks `serverAuth` EKU |
+| `no available certificate` | Keystore path/password incorrect or file 
permissions restrict access |
+| Handshake fails after rotation | New keystore file was not written 
atomically; file watcher may have read a partial file |
+| `No subject alternative names` | Server certificate does not include a DNS 
SAN matching the hostname used by the client |
+
+Check <%=vars.product_name%> logs for messages from 
`FileWatchingX509ExtendedKeyManager`
+(initialization and reload events) and for `SSLHandshakeException` details.
+
+## <a id="ica_references" class="no-quick-link"></a>References
+
+- [Configuring SSL](implementing_ssl.html) — general SSL configuration for
+  <%=vars.product_name%>
+- [SSL Sample Implementation](ssl_example.html) — example keystore/truststore
+  setup in <%=vars.product_name%>
+- [Public CA Client Authentication EKU 
Mitigations](public_ca_client_auth_eku_mitigations.html) — overview and other 
mitigation options
+- `FileWatchingX509ExtendedKeyManager`:
+  
`geode-core/src/main/java/org/apache/geode/internal/net/filewatch/FileWatchingX509ExtendedKeyManager.java`
+- `SSLConfig` and `SSLConfigurationFactory`:
+  `geode-core/src/main/java/org/apache/geode/internal/net/SSLConfig.java`
+- `SocketCreator`:
+  `geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java`
diff --git a/geode-docs/security/ssl_overview.html.md.erb 
b/geode-docs/security/ssl_overview.html.md.erb
index 7fa30463bf..5ad9539548 100644
--- a/geode-docs/security/ssl_overview.html.md.erb
+++ b/geode-docs/security/ssl_overview.html.md.erb
@@ -43,3 +43,13 @@ The SSL implementation ensures that only the applications 
identified by you can
 
     A simple example demonstrates the configuration and startup of 
<%=vars.product_name%> system components with SSL.
 
+-   **[Mitigating Public CA Client Authentication EKU 
Changes](public_ca_client_auth_eku_mitigations.html)**
+
+    Provides guidance for deployments affected by public Certificate 
Authorities removing or restricting the Client Authentication EKU from 
publicly-issued certificates. Covers three mitigation strategies:
+
+    -   **[Internal / Enterprise CA for mTLS](ssl_internal_ca_mtls.html)** — 
Operate an internal or enterprise CA to issue client certificates. Removes 
reliance on public CA EKU policies entirely.
+
+    -   **[Server-only TLS with Alternative Client 
Authentication](ssl_server_only_tls_alt_auth.html)** — Retain TLS transport 
encryption and authenticate clients at the application layer using 
<%=vars.product_name%>'s `AuthInitialize` and `SecurityManager` framework 
instead of client certificates.
+
+    -   **[Hybrid: Public-CA Server Certs with Private-CA Client 
Certs](ssl_hybrid_public_server_private_client.html)** — Keep server 
certificates from a public CA while issuing client certificates from an 
internal CA, preserving external trust for server endpoints while maintaining 
control over client identity.
+
diff --git a/geode-docs/security/ssl_server_only_tls_alt_auth.html.md.erb 
b/geode-docs/security/ssl_server_only_tls_alt_auth.html.md.erb
new file mode 100644
index 0000000000..886e1051a2
--- /dev/null
+++ b/geode-docs/security/ssl_server_only_tls_alt_auth.html.md.erb
@@ -0,0 +1,301 @@
+---
+title:  Server-only TLS with Alternative Client Authentication
+---
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+This page is part of the
+[Public CA Client Authentication EKU Mitigation 
guide](public_ca_client_auth_eku_mitigations.html).
+It describes how to configure <%=vars.product_name%> with TLS for transport
+encryption while authenticating clients at the application layer — removing the
+dependency on client certificates and the `clientAuth` EKU entirely.
+
+## <a id="soa_summary" class="no-quick-link"></a>Summary
+
+When server-only TLS is configured:
+
+- **All network traffic is encrypted in both directions** by TLS. Enabling TLS
+  on a <%=vars.product_name%> component (`ssl-enabled-components`) causes the
+  underlying JSSE socket/engine to encrypt all data for that component 
regardless
+  of whether client certificates are required.
+- **Client authentication uses application-layer mechanisms** — 
username/password,
+  token-based auth, LDAP/AD, or other custom `SecurityManager` implementations 
—
+  rather than TLS handshake client certificates.
+
+**When to choose this option:**
+
+- Client certificates are operationally impractical to distribute or rotate.
+- You already have or can build an application-layer authentication system.
+- You want the simplest migration path: keep TLS encryption, remove client 
certs.
+- You need a solution that works for both client/server and peer-to-peer (P2P)
+  cache topologies.
+
+## <a id="soa_transport_clarification" class="no-quick-link"></a>Transport 
Encryption Clarification
+
+A common question is whether disabling client certificate authentication 
(`ssl-require-authentication=false`)
+reduces transport security.  It does not.
+
+<%=vars.product_name%> TLS is implemented at the socket/engine layer by JSSE.
+Once a TLS connection is established, all bytes exchanged over that connection
+are encrypted and authenticated by the negotiated cipher suite — in both the
+client-to-server and server-to-client directions.  Client certificate
+authentication is a separate step in the TLS handshake that establishes the
+*client's identity*; it has no effect on the *confidentiality or integrity* of
+the channel.
+
+Setting `ssl-require-authentication=false` disables mandatory client 
certificate
+presentation during the handshake.  The TLS session is still established and
+data continues to flow over an encrypted channel.
+
+## <a id="soa_config" class="no-quick-link"></a>Configuration
+
+### Enable TLS on Servers and Locators (Server-only TLS)
+
+``` pre
+# Enable TLS for all components
+ssl-enabled-components=all
+
+# Server presents its certificate; client verifies it
+ssl-keystore=/etc/geode/server-keystore.jks
+ssl-keystore-password=<password>
+ssl-keystore-type=JKS
+
+# Do NOT require client certificates
+ssl-require-authentication=false
+
+# Optional but recommended: validate the server hostname from the client side
+ssl-endpoint-identification-enabled=true
+```
+
+**Note:** `ssl-require-authentication=false` is the key change from a full mTLS
+deployment.  The server still presents its own certificate and all transport
+remains TLS-encrypted.
+
+For component-specific control (for example, requiring mTLS on `cluster` but
+not on `server`), use the component-specific property variants:
+
+``` pre
+cluster-ssl-require-authentication=true
+server-ssl-require-authentication=false
+```
+
+### Configure Application-layer Client Authentication
+
+<%=vars.product_name%> supports pluggable authentication through:
+
+- **`AuthInitialize`** — a client-side interface whose `getCredentials()` 
method
+  injects credentials (as a `Properties` object) into each connection attempt.
+- **`SecurityManager`** — a server-side interface that receives the credentials
+  and enforces authentication and authorization.
+
+**Username / password (simplest approach):**
+
+``` pre
+# Client-side: supply credentials using an AuthInitialize implementation
+security-client-auth-init=org.apache.geode.security.templates.UserPasswordAuthInit.create
+
+# Server-side: validate credentials with a SecurityManager implementation
+security-manager=com.example.geode.security.MySecurityManager
+```
+
+A minimal `SecurityManager` implementation:
+
+```java
+public class MySecurityManager implements SecurityManager {
+    @Override
+    public Object authenticate(Properties credentials) throws 
AuthenticationFailedException {
+        String user = credentials.getProperty(ResourceConstants.USER_NAME);
+        String pass = credentials.getProperty(ResourceConstants.PASSWORD);
+        // validate against your directory / token store
+        if (!isValid(user, pass)) {
+            throw new AuthenticationFailedException("Invalid credentials for 
user: " + user);
+        }
+        return user; // returned value becomes the principal
+    }
+
+    @Override
+    public boolean authorize(Object principal, ResourcePermission permission) {
+        return true; // add fine-grained authorization here
+    }
+}
+```
+
+**Token-based authentication (JWT / OAuth bearer tokens):**
+
+Implement `AuthInitialize` to supply a token string and a `SecurityManager` to
+validate and decode that token:
+
+```java
+// Client side
+public class TokenAuthInit implements AuthInitialize {
+    public static AuthInitialize create() { return new TokenAuthInit(); }
+
+    @Override
+    public Properties getCredentials(Properties securityProps, 
DistributedMember server,
+                                     boolean isPeer) {
+        Properties creds = new Properties();
+        creds.setProperty("bearer-token", System.getenv("GEODE_BEARER_TOKEN"));
+        return creds;
+    }
+}
+```
+
+**LDAP / Active Directory:**
+
+Implement `SecurityManager.authenticate()` to verify the supplied credentials
+against an LDAP server using the standard `javax.naming.ldap` API or JNDI.
+
+## <a id="soa_p2p_topology" class="no-quick-link"></a>Peer-to-Peer (P2P) 
Topology Support
+
+This approach works for **both** client/server and peer-to-peer cache 
topologies.
+In P2P topologies, members authenticate with each other using the same
+application-layer authentication mechanism.
+
+**P2P Configuration:**
+
+``` pre
+ssl-enabled-components=all
+ssl-keystore=/etc/geode/peer-keystore.jks
+ssl-keystore-password=<password>
+ssl-truststore=/etc/geode/peer-truststore.jks
+ssl-truststore-password=<password>
+
+# Disable certificate-based peer authentication
+ssl-require-authentication=false
+ssl-endpoint-identification-enabled=true
+
+# Application-layer peer authentication
+security-peer-auth-init=com.example.geode.security.PeerAuthInit.create
+security-manager=com.example.geode.security.MySecurityManager
+security-username=${PEER_USERNAME}
+security-password=${PEER_PASSWORD}
+```
+
+**Authorization Requirement:**
+
+Peers joining a P2P cluster must have `CLUSTER:MANAGE` permission. The
+`SecurityManager.authorize()` method validates this during peer join:
+
+```java
+@Override
+public boolean authorize(Object principal, ResourcePermission permission) {
+    // Peer joining cluster must have CLUSTER:MANAGE
+    if (permission.getResource() == Resource.CLUSTER && 
+        permission.getOperation() == Operation.MANAGE) {
+        return hasClusterManagePermission(principal);
+    }
+    return authorizeDataOperation(principal, permission);
+}
+```
+
+## <a id="soa_client_driver" class="no-quick-link"></a>Client Driver Changes
+
+When migrating from mTLS to server-only TLS + credential auth:
+
+1. **Remove** the client keystore (`ssl-keystore`) configuration from client
+   driver properties — clients no longer present a certificate.
+2. **Add** credential injection via `security-client-auth-init` (or the
+   equivalent driver API for non-Java clients).
+3. Clients still need a truststore (or rely on the system trust store) to 
verify
+   the server certificate.
+
+Minimal client configuration example (Java thin client):
+
+``` pre
+# Keep truststore to verify the server cert
+ssl-enabled-components=all
+ssl-truststore=/etc/geode/client-truststore.jks
+ssl-truststore-password=<password>
+ssl-endpoint-identification-enabled=true
+
+# No ssl-keystore needed for server-only TLS
+
+# Credential injection
+security-client-auth-init=org.apache.geode.security.templates.UserPasswordAuthInit.create
+security-username=myuser
+security-password=mypassword
+```
+
+## <a id="soa_rotation" class="no-quick-link"></a>Server Certificate Rotation
+
+Server keystores can still be rotated without restart using
+`FileWatchingX509ExtendedKeyManager`.  Write the new server keystore atomically
+(create temp file, write, rename) to the path configured in `ssl-keystore`, and
+the file watcher reloads the `KeyManager` transparently.
+
+## <a id="soa_security_considerations" class="no-quick-link"></a>Security 
Considerations
+
+- Even without mutual certificate authentication, confidentiality and integrity
+  are preserved by TLS.  However, transport-level client identity assurances
+  (binding a TLS session to a certificate) are not available.  Enforce strong
+  application-layer authentication in your `SecurityManager`.
+- Protect credential stores.  Do not store plaintext passwords in configuration
+  files; set passwords from environment variables in start scripts, or use a 
secrets
+  management system.
+- Consider short-lived session tokens, rate limiting on login endpoints, and
+  audit logging within your `SecurityManager`.
+- If supported by your client driver, use per-connection or per-operation
+  credentials rather than long-lived shared secrets.
+
+## <a id="soa_verification" class="no-quick-link"></a>Verification
+
+**Enable JSSE debug logging** to confirm the cipher suite and handshake flow:
+
+```
+-Djavax.net.debug=ssl,handshake
+```
+
+When `ssl-require-authentication=false`, the handshake completes without 
requesting
+or presenting client certificates.
+
+**Common issues:**
+
+| Symptom | Likely cause |
+|---|---|
+| `SSLHandshakeException: PKIX path building failed` | Client truststore does 
not contain the server's CA |
+| `AuthenticationFailedException` | `SecurityManager` rejected credentials; 
check logs for detail |
+| `SSLHandshakeException` requesting a client cert | A component still has 
`ssl-require-authentication=true`; verify per-component settings |
+
+## <a id="soa_migration_path" class="no-quick-link"></a>Phased Migration Path
+
+If you need to migrate a running cluster without downtime:
+
+1. Deploy a `SecurityManager` that accepts both the old certificate principal
+   (extracted from existing mTLS sessions) **and** the new username/password
+   credentials.  This allows both old (cert) and new (credential) clients to
+   coexist.
+2. Gradually roll client drivers to credential-based auth.
+3. Once all clients use credential auth, change 
`ssl-require-authentication=false`
+   on servers and remove client keystore configuration from clients.
+4. (Optional) Remove the old CA from server truststores once no cert-based
+   clients remain.
+
+## <a id="soa_references" class="no-quick-link"></a>References
+
+- [Configuring SSL](implementing_ssl.html) — component SSL properties
+- [Authentication](authentication_overview.html) — `AuthInitialize` and
+  `SecurityManager` concepts
+- [Public CA Client Authentication EKU 
Mitigations](public_ca_client_auth_eku_mitigations.html) — overview and other 
mitigation options
+- `SSLConfig` and `SSLConfigurationFactory`:
+  `geode-core/src/main/java/org/apache/geode/internal/net/SSLConfig.java`
+- `SocketCreator`:
+  `geode-core/src/main/java/org/apache/geode/internal/net/SocketCreator.java`
+- `FileWatchingX509ExtendedKeyManager`:
+  
`geode-core/src/main/java/org/apache/geode/internal/net/filewatch/FileWatchingX509ExtendedKeyManager.java`
+- `AuthInitialize` test templates:
+  
`geode-core/src/test/java/org/apache/geode/security/templates/UserPasswordAuthInit.java`

Reply via email to