{"record":{"id":"3d5b0e189e32e00d","repo":"quarkusio/quarkus","slug":"quarkus-does-not-support-client-certificate-based","errorCode":null,"errorMessage":"Quarkus does not support Client Certificate based authentication","messagePattern":"Quarkus does not support Client Certificate based authentication","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/jdbc/jdbc-mssql/runtime/src/main/java/io/quarkus/jdbc/mssql/runtime/graal/com/microsoft/sqlserver/jdbc/SQLServerJDBCSubstitutions.java","lineNumber":56,"sourceCode":"\n    @Substitute\n    private void setKeyVaultProvider(String keyStorePrincipalId, String keyStoreSecret) throws SQLServerException {\n        throw new IllegalStateException(\"Quarkus does not support Keyvault-based column encryption\");\n    }\n\n    @Substitute\n    ArrayList<byte[]> initEnclaveParameters(SQLServerStatement statement, String userSql, String preparedTypeDefinitions,\n            QuarkusSqlParameter[] params, ArrayList<String> parameterNames) throws SQLServerException {\n        throw new IllegalStateException(\"Quarkus does not support AAS Enclave\");\n    }\n}\n\n@TargetClass(className = \"com.microsoft.sqlserver.jdbc.SQLServerCertificateUtils\")\nfinal class QuarkusSqlSQLServerCertificateUtils {\n    @Substitute\n    static KeyManager[] getKeyManagerFromFile(String certPath, String keyPath, String keyPassword)\n            throws IOException, GeneralSecurityException, SQLServerException {\n        throw new IllegalStateException(\"Quarkus does not support Client Certificate based authentication\");\n    }\n}\n\n@TargetClass(className = \"com.microsoft.sqlserver.jdbc.SQLServerLexer\")\n@Delete //Deleting this one explicitly, so to help with maintenance with the substitutions of SQLServerFMTQuery\nfinal class SQLServerLexerRemove {\n\n}\n\n/**\n * This will make sure the ANTLR4 Lexer included in the driver is not reachable; this was mostly\n * prevented by not allowing to explicitly set the useFmtOnly connection property, but this code\n * path would also get activated on very old SQL Server versions being detected on a connection.\n * Since that's not a constant that the compiler can rely on, we need one more substitution.\n */\n@TargetClass(className = \"com.microsoft.sqlserver.jdbc.SQLServerFMTQuery\")\nfinal class SQLServerFMTQuery {\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/jdbc/jdbc-mssql/runtime/src/main/java/io/quarkus/jdbc/mssql/runtime/graal/com/microsoft/sqlserver/jdbc/SQLServerJDBCSubstitutions.java#L38-L74","documentation":"Quarkus substitutes SQLServerCertificateUtils.getKeyManagerFromFile to throw IllegalStateException in native mode. Client certificate authentication (TLS client cert via PEM cert/key files) in the MSSQL driver relies on crypto code excluded from the native image, so it is explicitly rejected.","triggerScenarios":"Native-mode connection configured with clientCertificate / clientKey (PEM files) for client certificate authentication to SQL Server, reaching getKeyManagerFromFile(certPath, keyPath, keyPassword).","commonSituations":"Mutual TLS setups using client certs; connection strings copied from containers/services that authenticate with client certificates; hardening configurations requiring cert-based auth.","solutions":["Remove clientCertificate/clientKey settings and authenticate via user/password or Kerberos","Convert the client certificate into a Java KeyStore and use standard SSL keystore configuration (javax.net.ssl.keyStore) if the driver path supports it in native","Terminate mTLS at a proxy/sidecar and connect to it plainly or with server-only TLS","Use JVM mode where client-certificate authentication works"],"exampleFix":"// before\nString url = \"jdbc:sqlserver://host;database=db;clientCertificate=/certs/client.pem;clientKey=/certs/client.key\";\n// after\nString url = \"jdbc:sqlserver://host;database=db;user=app;password=...\";","handlingStrategy":"validation","validationCode":"if (url.contains(\"clientCertificate=\") || url.contains(\"clientKey=\")) { throw new IllegalArgumentException(\"Client certificate auth is not supported in native mode\"); }","typeGuard":"static boolean usesClientCertAuth(String url) { return url != null && (url.contains(\"clientCertificate=\") || url.contains(\"clientKey=\")); }","tryCatchPattern":"try { conn = ds.getConnection(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Client Certificate\")) { log.error(\"Use SQL/Kerberos auth instead of client certs in native mode\"); } throw e; }","preventionTips":["Avoid clientCertificate/clientKey URL params in native configs","Terminate mTLS at a proxy when native support is required","Standardize on SQL or Kerberos authentication for native builds","Verify certificate-based auth in a native smoke test before rollout"],"tags":["native-image","jdbc","mssql","client-certificate","mtls"],"backgroundTag":"native-image-unsupported-feature","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}