Skip to content

Commit f857d15

Browse files
committed
test(sea): live TLS e2e for checkServerCertificate + customCaCert
End-to-end coverage against a real workspace (PAT), skipped when secrets are absent: - default permissive: connects + SELECT 1 - strict (checkServerCertificate: true): the real publicly-signed workspace cert validates against the system roots - strict + additive customCaCert as PEM string and as Buffer: an extra self-signed root does not break system-root validation - malformed customCaCert (PEM header, garbage body): kernel rejects The additive CA is embedded so the suite is self-contained in CI. Verified locally: 5/5 pass. Separately confirmed the negative security case with a local self-signed HTTPS server — strict is rejected at the TLS layer while permissive gets past TLS to the HTTP response. Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
1 parent 4281a94 commit f857d15

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright (c) 2026 Databricks, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import { expect } from 'chai';
16+
import { DBSQLClient } from '../../../lib';
17+
18+
/**
19+
* A throwaway self-signed CA, embedded so the suite is self-contained
20+
* (no external file dependency in CI). It is added to the trust store as
21+
* an *additional* root in the customCaCert tests; the real workspace cert
22+
* still validates via the system roots, so this cert is never actually in
23+
* the validation path — its expiry is irrelevant.
24+
*/
25+
const THROWAWAY_CA_PEM = `-----BEGIN CERTIFICATE-----
26+
MIIDGTCCAgGgAwIBAgIUdW39pdaepg+Mfb++pCKm9FxYlkswDQYJKoZIhvcNAQEL
27+
BQAwHDEaMBgGA1UEAwwRdGhyb3dhd2F5LXRlc3QtY2EwHhcNMjYwNTMxMjEzNDI1
28+
WhcNMjYwNjAxMjEzNDI1WjAcMRowGAYDVQQDDBF0aHJvd2F3YXktdGVzdC1jYTCC
29+
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWHhz4wQsBNqHJJzqJgT0BL
30+
DO9oqZT2zsAnHOWPchsLoAjeBJ4oXgNjh2ZeH1FH4kThGw/giL5VDpO+lVmMu5TG
31+
jeXXAmPIXk27qi1mGqu/tqstzuSqyxxk3oDnJuxCFxBYyA9LG+rhjH9WsW1XvzGn
32+
gOQLZ0Hjx4FkA+aWvH8AV82OUgHRRHfe1GaU4MUsLMYGU+2bwngcL059pBP/h/BS
33+
Q5brMJnFi8UrVTizuCF/QYP5dtEyvDltMKKU/E8uft/DP/2Q25r0hMZNU+I22v0N
34+
Ya8gCzA47LMPeIaZ3tGT94OEyUaU5mpwsVwL4Y6bfQRtEIph6qwJnAjWwJxQsssC
35+
AwEAAaNTMFEwHQYDVR0OBBYEFCDYsRm4L4QEbzu3Vkm+ji82xZcNMB8GA1UdIwQY
36+
MBaAFCDYsRm4L4QEbzu3Vkm+ji82xZcNMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
37+
hvcNAQELBQADggEBAJBXM668YVQ+PcrolpH0MisuUkqyjcrMLLDsjqU4PmBv75BZ
38+
m08hffg1qVRjYnqvFYbYaStuvousuIT5h7cS5y0I5rMEzeRi2+MaOB3gaDBofObH
39+
RYpCsehOjiNoNxoTzIIwZh+aNf/LK/Ti+DcW7dgxAlrctPbzZGQt/2wQLK/OLn6X
40+
0FyAJDMQ7l1MOL5wZ4JTd+EImlbwMIj73sug9elXfYGNu2UzqZ82iQFUxaBEuckJ
41+
O+tldQDDMuvU2m5bFypPXu/3Fe25FDFQggdOE1i+sp9WkoW5zh8GKo1y53yjbNAk
42+
7bq2fNLgT9r2D54uqpuJwCMshIUTi5p60GNNPSo=
43+
-----END CERTIFICATE-----
44+
`;
45+
46+
/**
47+
* SEA TLS end-to-end against a live workspace. Exercises the
48+
* `checkServerCertificate` toggle and `customCaCert` passthrough end to
49+
* end (DBSQLClient → SeaBackend → SeaAuth → napi → kernel rustls →
50+
* real Databricks TLS handshake).
51+
*
52+
* Required env (exported by `~/.zshrc`):
53+
* - DATABRICKS_PECOTESTING_SERVER_HOSTNAME
54+
* - DATABRICKS_PECOTESTING_HTTP_PATH
55+
* - DATABRICKS_PECOTESTING_TOKEN_PERSONAL (or _TOKEN)
56+
*
57+
* Skipped when secrets are absent.
58+
*/
59+
describe('sea-tls e2e — checkServerCertificate + customCaCert through a live TLS handshake', function suite() {
60+
const host = process.env.DATABRICKS_PECOTESTING_SERVER_HOSTNAME;
61+
const path = process.env.DATABRICKS_PECOTESTING_HTTP_PATH;
62+
const token = process.env.DATABRICKS_PECOTESTING_TOKEN_PERSONAL || process.env.DATABRICKS_PECOTESTING_TOKEN;
63+
64+
this.timeout(120_000);
65+
66+
before(function gate() {
67+
if (!host || !path || !token) {
68+
// eslint-disable-next-line no-invalid-this
69+
this.skip();
70+
}
71+
});
72+
73+
async function connectAndSelectOne(extra: Record<string, unknown>): Promise<Array<Record<string, unknown>>> {
74+
const client = new DBSQLClient();
75+
await client.connect({
76+
host: host as string,
77+
path: path as string,
78+
token: token as string,
79+
useSEA: true,
80+
...extra,
81+
});
82+
const session = await client.openSession();
83+
const operation = await session.executeStatement('SELECT 1 AS one', {});
84+
const rows = (await operation.fetchAll()) as Array<Record<string, unknown>>;
85+
await operation.close();
86+
await session.close();
87+
await client.close();
88+
return rows;
89+
}
90+
91+
it('default (permissive, no flag): connects and runs SELECT 1', async () => {
92+
const rows = await connectAndSelectOne({});
93+
expect(rows).to.deep.equal([{ one: 1 }]);
94+
});
95+
96+
it('strict (checkServerCertificate: true): real workspace cert validates against system roots', async () => {
97+
// The important positive case — turning verification ON must NOT
98+
// break against a real, publicly-signed Databricks cert.
99+
const rows = await connectAndSelectOne({ checkServerCertificate: true });
100+
expect(rows).to.deep.equal([{ one: 1 }]);
101+
});
102+
103+
it('strict + additive customCaCert (PEM string): extra root does not break system-root validation', async () => {
104+
// A throwaway self-signed CA is added on top of the system roots.
105+
// The real workspace cert still validates via the system roots, so
106+
// the connection succeeds — proving custom_ca_cert is additive.
107+
const rows = await connectAndSelectOne({
108+
checkServerCertificate: true,
109+
customCaCert: THROWAWAY_CA_PEM,
110+
});
111+
expect(rows).to.deep.equal([{ one: 1 }]);
112+
});
113+
114+
it('strict + additive customCaCert (Buffer): same, passed as bytes', async () => {
115+
const rows = await connectAndSelectOne({
116+
checkServerCertificate: true,
117+
customCaCert: Buffer.from(THROWAWAY_CA_PEM, 'utf8'),
118+
});
119+
expect(rows).to.deep.equal([{ one: 1 }]);
120+
});
121+
122+
it('malformed customCaCert (PEM header, garbage body): kernel rejects at connect/openSession', async () => {
123+
const garbage = '-----BEGIN CERTIFICATE-----\nnot-valid-base64-cert-bytes\n-----END CERTIFICATE-----\n';
124+
const client = new DBSQLClient();
125+
let threw = false;
126+
try {
127+
await client.connect({
128+
host: host as string,
129+
path: path as string,
130+
token: token as string,
131+
useSEA: true,
132+
checkServerCertificate: true,
133+
customCaCert: garbage,
134+
});
135+
await client.openSession();
136+
} catch (err) {
137+
threw = true;
138+
expect(String((err as Error).message).length).to.be.greaterThan(0);
139+
} finally {
140+
await client.close().catch(() => undefined);
141+
}
142+
expect(threw, 'expected a malformed custom CA to be rejected').to.equal(true);
143+
});
144+
});

0 commit comments

Comments
 (0)