Skip to content

Commit 332cbe5

Browse files
authored
feat(service-provider-server): use OS DNS for SRV records MONGOSH-733 (#862)
1 parent e3a8cb0 commit 332cbe5

File tree

6 files changed

+141
-2
lines changed

6 files changed

+141
-2
lines changed

packages/build/src/compile/signable-compiler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ export class SignableCompiler {
6666
path: await findModulePath('service-provider-server', 'mongodb-client-encryption'),
6767
requireRegexp: /\bmongocrypt\.node$/
6868
};
69+
const osDnsAddon = {
70+
path: await findModulePath('service-provider-server', 'os-dns-native'),
71+
requireRegexp: /\bos_dns_native\.node$/
72+
};
6973
const winCAAddon = process.platform === 'win32' ? {
7074
path: await findModulePath('cli-repl', 'win-export-certificate-and-key'),
7175
requireRegexp: /\bwin_export_cert\.node$/
@@ -93,7 +97,8 @@ export class SignableCompiler {
9397
AWS_SECRET_ACCESS_KEY: process.env.DEVTOOLS_CI_AWS_SECRET
9498
},
9599
addons: [
96-
fleAddon
100+
fleAddon,
101+
osDnsAddon
97102
].concat(winCAAddon ? [
98103
winCAAddon
99104
] : []).concat(macKeychainAddon ? [

packages/connectivity-tests/test/atlas.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,24 @@ function test_data_lake() {
129129
check_failed
130130
}
131131

132+
function test_srv_without_nodejs_dns() {
133+
printf "test_srv_without_nodejs_dns ... "
134+
135+
CONNECTION_STRING="mongodb+srv://${ATLAS_USERNAME}:${ATLAS_PASSWORD}@${ATLAS_HOSTNAME}/admin"
136+
137+
echo "${CONNECTION_STATUS_COMMAND}" | NODE_OPTIONS="-r ${MONGOSH_ROOT_DIR}/testing/disable-dns-srv.js" mongosh "${CONNECTION_STRING}" |
138+
grep -Fq "${CONNECTION_STATUS_CHECK_STRING}" ||
139+
FAILED="Can't connect to Atlas using connection string without Node.js SRV/TXT DNS support"
140+
141+
check_failed
142+
}
143+
132144
test_connection_string
133145
test_atlas_in_logs
134146
test_credentials_masking
135147
test_cli_args
136148
test_password_prompt
137149
test_data_lake
150+
test_srv_without_nodejs_dns
138151

139152
echo "All Atlas tests are passing"

packages/service-provider-server/package-lock.json

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/service-provider-server/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
"@types/bl": "^2.1.0"
5151
},
5252
"optionalDependencies": {
53-
"mongodb-client-encryption": "^1.2.3"
53+
"mongodb-client-encryption": "^1.2.3",
54+
"os-dns-native": "^1.0.3",
55+
"resolve-mongodb-srv": "^1.0.1"
5456
}
5557
}

packages/service-provider-server/src/cli-service-provider.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,28 @@ async function connectWithFailFast(client: MongoClient): Promise<void> {
159159
}
160160
}
161161

162+
let resolveDnsHelpers: {
163+
resolve: typeof import('resolve-mongodb-srv'),
164+
osDns: typeof import('os-dns-native')
165+
} | undefined = undefined;
166+
167+
async function resolveMongodbSrv(uri: string): Promise<string> {
168+
if (uri.startsWith('mongodb+srv://')) {
169+
try {
170+
resolveDnsHelpers ??= {
171+
resolve: require('resolve-mongodb-srv'),
172+
osDns: require('os-dns-native')
173+
};
174+
} catch { /* ignore */ }
175+
if (resolveDnsHelpers !== undefined) {
176+
return await resolveDnsHelpers.resolve(uri, {
177+
dns: resolveDnsHelpers.osDns.withNodeFallback
178+
});
179+
}
180+
}
181+
return uri;
182+
}
183+
162184
/**
163185
* Connect a MongoClient. If AutoEncryption is requested, first connect without the encryption options and verify that
164186
* the connection is to an enterprise cluster. If not, then error, otherwise close the connection and reconnect with the
@@ -186,6 +208,7 @@ export async function connectMongoClient(uri: string, clientOptions: MongoClient
186208
}
187209
await client.close();
188210
}
211+
uri = await resolveMongodbSrv(uri);
189212
const client = new MClient(uri, clientOptions);
190213
await connectWithFailFast(client);
191214
return client;

testing/disable-dns-srv.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
const dns = require('dns');
3+
console.log('!!! Disabling SRV and TXT DNS queries through the Node.js API !!!');
4+
5+
const origResolve = dns.resolve;
6+
const origPromiseResolve = dns.promises.resolve;
7+
const err = Object.assign(new Error('SRV and TXT not available'), { code: 'ENODATA' });
8+
9+
dns.resolve = (hostname, type, cb) => {
10+
if (type === 'SRV' || type === 'TXT')
11+
return process.nextTick(cb, err);
12+
return origResolve(hostname, type, cb);
13+
};
14+
dns.resolveSrv = (hostname, cb) => {
15+
return process.nextTick(cb, err);
16+
};
17+
dns.resolveTxt = (hostname, cb) => {
18+
return process.nextTick(cb, err);
19+
};
20+
dns.promises.resolve = async(hostname, type) => {
21+
if (type === 'SRV' || type === 'TXT')
22+
throw err;
23+
await origPromiseResolve;
24+
};
25+
dns.promises.resolveSrv = () => Promise.reject(err);
26+
dns.promises.resolveTxt = () => Promise.reject(err);

0 commit comments

Comments
 (0)