Hello!

After some research, docs, and test, I didn't found an answer to my issue.

I'm writing to the list  because I have to configure a probably not very common 
Tomcat configuration and didn't found correct configuration of if it is posible 
to do it.
Also I didn't find previous information or examples on internet and the wiki.

There is a similar question in Server Fault 
https://serverfault.com/questions/1161457/can-i-use-certificates-in-the-local-machine-from-a-managed-service-account,
 but not solved yet.

The configuration has been also involved with a JDK recent bug-fix (but 10 
years old), but this part is fixed using latest available JDK versions.
So I think it would be valuable to document an Use Case based on real 
experience that can be both, tested in future versions, and also useful for 
future users, available in the wiki or official docs :-)

May be what's I'm trying to do is not really possible, but need to know if this 
is a Tomcat limitation or a Windows one.

My actual configuration

Server version name:   Apache Tomcat/9.0.65
Server version number: 9.0.65.0
Server built:          Jul 14 2022 12:28:53 UTC
Architecture:          amd64
OS Version:            10.0
OS Name:               Windows Server 2019
JVM Vendor:            Eclipse Adoptium
JVM Version:           11.0.23+9
Java Home:             
C:\OpenJDK11U-jdk_x64_windows_hotspot_11.0.23_9\jdk-11.0.23+9

Actual secure configuration used:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
server="Unknown"
maxThreads="150" scheme="https" secure="true"
 enableLookups="true"
 KeystoreType="Windows-MY-LOCALMACHINE"
clientAuth="false" sslProtocol="TLS"
KeystoreFile=""
KeyAlias="tomcat" />


Configuration:
- The certificate is in the LOCALMACHINE Windows Storage and allows read access 
to the user "account1$" which is an AD Managed Service Account.
-

Facts:
- If the user have read access but not local admin, then the previous stack 
trace is generated.
- If I give local Admin rights to the service account, it seems can access to 
the Certificate Storage, in other case, the previous Stack Trace is generated.
- Unless I gave local Admin rights, apache opens port 8443, but doesn't respond 
to requests on 8443 when testing and no error in logs appears.

What is the question is "How to configure Tomcat with a Managed Service Account 
when using LocalMachine certificates for TLS"

Notes:
- JDK 11.0.20+ is required due a well known bug that has been backported from 
JDK 21  [JDK-6782021] It is not possible to read local computer certificates 
with the SunMSCAPI provider - Java Bug System 
(openjdk.org<http://openjdk.org/>) 
(https://bugs.openjdk.org/browse/JDK-6782021) and [JDK-8303520] It is not 
possible to read local computer certificates with the SunMSCAPI provider - Java 
Bug System (openjdk.org<http://openjdk.org/>) 
(https://bugs.openjdk.org/browse/JDK-8303520)

Next program can help to check different configurations, and it works when the 
certificate has read permission for the user who is running it.

// JDK8313367test.java - Simple test case to demonstrate OpenJDK defect 
JDK-8313367
// References:
// * https://bugs.java.com/bugdatabase/view_bug?bug_id=JDK-8313367
// * 
https://stackoverflow.com/questions/75255985/java-keystore-type-windows-my-root-localmachine-requires-administrator-permissio

/*
Here is the command line to run the test using JDK 11.0.20+,  17.0.20+ or 
20.0.2+
java --add-modules=jdk.crypto.mscapi 
--add-exports=jdk.crypto.mscapi/sun.security.mscapi=ALL-UNNAMED 
JDK8313367test.java
*/

import java.io.*;
import java.security.KeyStore;
import java.security.Security;
import java.util.Enumeration;
import sun.security.mscapi.SunMSCAPI;

public class JDK8313367test {
    public static void main(String[] args) {
        try {
            Security.addProvider(new SunMSCAPI());
            KeyStore keyStore = KeyStore.getInstance("Windows-My-LOCALMACHINE");
            // When running as non-elevated, the SunMSCAPI provider, enhanced 
with JDK-6782021, incorrectly
                  // triggers system error 5 "Access is denied" when attempting 
to load the keystore when invoking the following method:
                  keyStore.load(null, null);
            Enumeration<String> aliases = keyStore.aliases();
                  // Print Friendly Names, a.k.a. aliases, of each certificate 
in the keystore
            for (int i = 0 ; aliases.hasMoreElements() ; i++) {
                        System.out.println( aliases.nextElement() );
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Pending tests:
- What I haven't tested, but it is an idea to test, is to launch this code from 
Tomcat and validate if it works (It isn't possible to run a CLI program using a 
Managed Service Account as per my knowledge). In case this test succeeds, it 
would mean the program flow in tomcat side is doing something different with 
ACL or something.
Thank you in advance for your support.
Please, send me back any question or clarification about the Use Case I could 
miss.
/Gavioto

Reply via email to