Skip to content

Commit f853f75

Browse files
authored
Add TDS 8.0 support for SQL Server Strict Encryption (#1643)
* Add TDS 8.0 support for SQL Server Strict Encryption Closes #1476 This adds support for SQL Server TDS 8.0 protocol which enables strict encryption mode. The implementation includes: - New 'encrypt' option supporting OFF, ON, and STRICT modes - TDS 8.0 protocol support with mandatory encryption and certificate validation - Backward compatibility with existing encryption behavior - Comprehensive test coverage for all encryption modes Some portions of this content were created with the assistance of Claude Code. Signed-off-by: Thomas Segismont <tsegismont@gmail.com> * Update docker-compose.yml to enable 2025-latest version usage Workaround for microsoft/mssql-docker#951 Signed-off-by: Thomas Segismont <tsegismont@gmail.com> --------- Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
1 parent 76a5e92 commit f853f75

22 files changed

+657
-109
lines changed

.github/workflows/ci-matrix-5.x.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ jobs:
4747
jdk: 11
4848
profile: 'MSSQL-2019-latest'
4949
module: 'vertx-mssql-client'
50+
- os: ubuntu-latest
51+
jdk: 11
52+
profile: 'MSSQL-2025-latest'
53+
module: 'vertx-mssql-client'
5054
- os: ubuntu-latest
5155
jdk: 11
5256
profile: 'DB2-11.5'
@@ -70,6 +74,10 @@ jobs:
7074
jdk: 25
7175
profile: 'MSSQL-2019-latest'
7276
module: 'vertx-mssql-client'
77+
- os: ubuntu-latest
78+
jdk: 25
79+
profile: 'MSSQL-2025-latest'
80+
module: 'vertx-mssql-client'
7381
- os: ubuntu-latest
7482
jdk: 25
7583
profile: 'Oracle-23'

vertx-mssql-client/README.adoc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ You can test with different SQL Server versions by using Maven profiles:
2626
----
2727
mvn test -P MSSQL-2017-latest
2828
mvn test -P MSSQL-2019-latest
29+
mvn test -P MSSQL-2025-latest
2930
----
3031

3132
Or by passing the version property directly:
@@ -38,7 +39,8 @@ mvn test -Dmssql-container.version=2017-latest
3839
The following versions are supported:
3940

4041
* `2017-latest`
41-
* `2019-latest` (default)
42+
* `2019-latest`
43+
* `2025-latest` (default)
4244

4345
==== Testing with an external database
4446

@@ -57,9 +59,11 @@ Then run tests against it:
5759
mvn test \
5860
-Dconnection.uri=sqlserver://SA:A_Str0ng_Required_Password@localhost:1433 \
5961
-Dtls.connection.uri=sqlserver://SA:A_Str0ng_Required_Password@localhost:1435 \
60-
-Dforce.encryption.connection.uri=sqlserver://SA:A_Str0ng_Required_Password@localhost:1437
62+
-Dforce.encryption.connection.uri=sqlserver://SA:A_Str0ng_Required_Password@localhost:1437 \
63+
-Dstrict.encryption.connection.uri=sqlserver://SA:A_Str0ng_Required_Password@localhost:1439?encrypt=strict
6164
----
6265

66+
* `connection.uri`: connection uri of the database to use for all other tests
6367
* `tls.connection.uri`: connection uri of the database to use for `MSSQLEncryptionTest`
6468
* `force.encryption.connection.uri`: connection uri of the database to use for `MSSQLForcedEncryptionTest`
65-
* `connection.uri`: connection uri of the database to use for all other tests
69+
* `strict.encryption.connection.uri`: connection uri of the database to use for `MSSQLStrictEncryptionTest`

vertx-mssql-client/docker/docker-compose.yml

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@ version: "3.9"
22

33
services:
44
test-mssql:
5-
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2019-latest}
5+
# Set cpus and cpuset untilhttps://github.com/microsoft/mssql-docker/issues/951 is resolved
6+
cpus: 1
7+
cpuset: "0"
8+
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
69
ports:
710
- "1433:1433"
811
environment:
912
ACCEPT_EULA: Y
1013
TZ: UTC
1114
SA_PASSWORD: A_Str0ng_Required_Password
1215
test-mssql-initdb:
13-
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2019-latest}
16+
# Set cpus and cpuset untilhttps://github.com/microsoft/mssql-docker/issues/951 is resolved
17+
cpus: 1
18+
cpuset: "0"
19+
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
1420
depends_on:
1521
- "test-mssql"
1622
command: [ "sh", "/opt/mssql-tools18/bin/initdb.sh","test-mssql,1433","A_Str0ng_Required_Password","/opt/data/init.sql" ]
@@ -24,7 +30,10 @@ services:
2430
target: /opt/data/init.sql
2531
read_only: true
2632
test-mssql-tls:
27-
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2019-latest}
33+
# Set cpus and cpuset untilhttps://github.com/microsoft/mssql-docker/issues/951 is resolved
34+
cpus: 1
35+
cpuset: "0"
36+
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
2837
ports:
2938
- "1435:1433"
3039
environment:
@@ -45,7 +54,10 @@ services:
4554
target: /etc/ssl/certs/mssql.pem
4655
read_only: true
4756
test-mssql-force-encryption:
48-
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2019-latest}
57+
# Set cpus and cpuset untilhttps://github.com/microsoft/mssql-docker/issues/951 is resolved
58+
cpus: 1
59+
cpuset: "0"
60+
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
4961
ports:
5062
- "1437:1433"
5163
environment:
@@ -65,3 +77,27 @@ services:
6577
source: ../src/test/resources/mssql.pem
6678
target: /etc/ssl/certs/mssql.pem
6779
read_only: true
80+
test-mssql-strict-encryption:
81+
# Set cpus and cpuset untilhttps://github.com/microsoft/mssql-docker/issues/951 is resolved
82+
cpus: 1
83+
cpuset: "0"
84+
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
85+
ports:
86+
- "1439:1433"
87+
environment:
88+
ACCEPT_EULA: Y
89+
TZ: UTC
90+
SA_PASSWORD: A_Str0ng_Required_Password
91+
volumes:
92+
- type: bind
93+
source: ../src/test/resources/mssql-strict-encryption.conf
94+
target: /var/opt/mssql/mssql.conf
95+
read_only: true
96+
- type: bind
97+
source: ../src/test/resources/mssql.key
98+
target: /etc/ssl/certs/mssql.key
99+
read_only: true
100+
- type: bind
101+
source: ../src/test/resources/mssql.pem
102+
target: /etc/ssl/certs/mssql.pem
103+
read_only: true

vertx-mssql-client/pom.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright (c) 2011-2026 Contributors to the Eclipse Foundation
4+
~
5+
~ This program and the accompanying materials are made available under the
6+
~ terms of the Eclipse Public License 2.0 which is available at
7+
~ http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
8+
~ which is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
~
10+
~ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
11+
-->
12+
213
<project xmlns="http://maven.apache.org/POM/4.0.0"
314
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
415
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@@ -20,6 +31,7 @@
2031
<!-- Set to a value for testing with a specific database -->
2132
<mssql-container.version/>
2233
<force.encryption.connection.uri/>
34+
<strict.encryption.connection.uri/>
2335
<vertx.asciidoc.sources.dir>${project.basedir}/src/main/asciidoc/*.adoc,${project.basedir}/../vertx-sql-client/src/main/asciidoc/*.adoc</vertx.asciidoc.sources.dir>
2436
</properties>
2537

@@ -67,6 +79,7 @@
6779
<connection.uri>${connection.uri}</connection.uri>
6880
<tls.connection.uri>${tls.connection.uri}</tls.connection.uri>
6981
<force.encryption.connection.uri>${force.encryption.connection.uri}</force.encryption.connection.uri>
82+
<strict.encryption.connection.uri>${strict.encryption.connection.uri}</strict.encryption.connection.uri>
7083
</systemPropertyVariables>
7184
</configuration>
7285
</plugin>
@@ -86,6 +99,12 @@
8699
<mssql-container.version>2019-latest</mssql-container.version>
87100
</properties>
88101
</profile>
102+
<profile>
103+
<id>MSSQL-2025-latest</id>
104+
<properties>
105+
<mssql-container.version>2025-latest</mssql-container.version>
106+
</properties>
107+
</profile>
89108
</profiles>
90109

91110
</project>

vertx-mssql-client/src/main/asciidoc/index.adoc

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ Currently, the client supports the following parameter keys:
127127
* `user`
128128
* `password`
129129
* `database`
130+
* `encrypt` - encryption mode: `strict` (TDS 8.0), `true` (TDS 7.x with SSL), `false` (no encryption)
130131

131132
Additional parameters will be added to the {@link io.vertx.sqlclient.SqlConnectOptions#getProperties properties}.
132133

@@ -323,9 +324,56 @@ You can set a handler on a connection to catch them and do something useful with
323324

324325
== Using SSL/TLS
325326

326-
=== Encryption level negotiation
327+
The client supports both TDS 7.x encryption and TDS 8.0 strict encryption.
327328

328-
When a connection is established, the client and the server negotiate the encryption level.
329+
=== Encryption Modes
330+
331+
The client supports three {@link io.vertx.mssqlclient.EncryptionMode encryption modes}:
332+
333+
* `OFF` - No encryption (the default)
334+
* `ON` - Optional encryption (equivalent to `ssl=true`)
335+
* `STRICT` - Strict TDS 8.0 encryption
336+
337+
=== TDS 8.0 and Strict Encryption
338+
339+
Starting with SQL Server 2022, Microsoft introduced TDS 8.0, a new version of the Tabular Data Stream that requires encryption for the entire connection from the start.
340+
341+
To connect to a SQL Server 2022+ instance with strict encryption:
342+
343+
[source,$lang]
344+
----
345+
{@link examples.MSSQLClientExamples#strictEncryption}
346+
----
347+
348+
Using connection URI:
349+
350+
----
351+
sqlserver://localhost:1433/testdb?user=sa&password=xxx&encrypt=strict
352+
----
353+
354+
[IMPORTANT]
355+
====
356+
TDS 8.0 requires proper certificate validation.
357+
Therefore, the `trustAll` option is not allowed with `STRICT` encryption mode.
358+
====
359+
360+
=== TDS 7.x Encryption (Legacy)
361+
362+
==== Encryption level negotiation
363+
364+
When using TDS 7.x (`OFF` or `ON` mode), the client and server negotiate the encryption level.
365+
366+
[NOTE]
367+
====
368+
The {@link io.vertx.mssqlclient.MSSQLConnectOptions} class maintains synchronization between the `encryptionMode` and `ssl` properties:
369+
370+
* Setting `encryptionMode` to `OFF` sets `ssl` to `false`
371+
* Setting `encryptionMode` to `ON` sets `ssl` to `true`
372+
* Setting `ssl` to `false` sets `encryptionMode` to `OFF`
373+
* Setting `ssl` to `true` sets `encryptionMode` to `ON`
374+
375+
This ensures consistency between the legacy `ssl` property and the newer `encryptionMode` property.
376+
====
329377

330378
The negotiated level depends on the client config in {@link io.vertx.mssqlclient.MSSQLConnectOptions} and the server config:
331379

@@ -339,7 +387,7 @@ The negotiation fails if `ssl` is set to `true` in client options, and the serve
339387
In this case, the client terminates the connection.
340388
====
341389

342-
=== Configuration
390+
==== Configuration
343391

344392
To configure `ssl` in client options, use the {@link io.vertx.mssqlclient.MSSQLConnectOptions#setSsl} method.
345393
By default, `ssl` is set to `false`.

vertx-mssql-client/src/main/generated/io/vertx/mssqlclient/MSSQLConnectOptionsConverter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, MSSQLCo
2222
obj.setSsl((Boolean)member.getValue());
2323
}
2424
break;
25+
case "encryptionMode":
26+
if (member.getValue() instanceof String) {
27+
obj.setEncryptionMode(io.vertx.mssqlclient.EncryptionMode.valueOf((String)member.getValue()));
28+
}
29+
break;
2530
}
2631
}
2732
}
@@ -33,5 +38,8 @@ static void toJson(MSSQLConnectOptions obj, JsonObject json) {
3338
static void toJson(MSSQLConnectOptions obj, java.util.Map<String, Object> json) {
3439
json.put("packetSize", obj.getPacketSize());
3540
json.put("ssl", obj.isSsl());
41+
if (obj.getEncryptionMode() != null) {
42+
json.put("encryptionMode", obj.getEncryptionMode().name());
43+
}
3644
}
3745
}

vertx-mssql-client/src/main/java/examples/MSSQLClientExamples.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
2+
* Copyright (c) 2011-2026 Contributors to the Eclipse Foundation
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License 2.0 which is available at
@@ -15,6 +15,7 @@
1515
import io.vertx.core.net.ClientSSLOptions;
1616
import io.vertx.core.net.PemTrustOptions;
1717
import io.vertx.docgen.Source;
18+
import io.vertx.mssqlclient.EncryptionMode;
1819
import io.vertx.mssqlclient.MSSQLBuilder;
1920
import io.vertx.mssqlclient.MSSQLConnectOptions;
2021
import io.vertx.mssqlclient.MSSQLConnection;
@@ -339,6 +340,14 @@ public void usingTrustOptions() {
339340
.setSslOptions(new ClientSSLOptions().setTrustOptions(new PemTrustOptions().addCertPath("/path/to/server-cert.pem")));
340341
}
341342

343+
public void strictEncryption() {
344+
MSSQLConnectOptions connectOptions = new MSSQLConnectOptions()
345+
.setEncryptionMode(EncryptionMode.STRICT)
346+
.setSslOptions(new ClientSSLOptions()
347+
// Strict encryption mode requires proper certificate validation
348+
.setTrustOptions(new PemTrustOptions().addCertPath("/path/to/server-cert.pem")));
349+
}
350+
342351
public void infoHandler(MSSQLConnection connection) {
343352
connection.infoHandler(info -> {
344353
System.out.println("Received info " + info.getSeverity() + "" + info.getMessage());
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2011-2026 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
12+
package io.vertx.mssqlclient;
13+
14+
import io.vertx.codegen.annotations.VertxGen;
15+
16+
/**
17+
* Encryption mode for SQL Server connections.
18+
*/
19+
@VertxGen
20+
public enum EncryptionMode {
21+
/**
22+
* No encryption (TDS 7.x).
23+
*/
24+
OFF,
25+
/**
26+
* Optional encryption (TDS 7.x).
27+
*/
28+
ON,
29+
/**
30+
* Mandatory TDS 8.0 encryption.
31+
*/
32+
STRICT
33+
}

0 commit comments

Comments
 (0)