Skip to content

Commit 747528b

Browse files
committed
feat(NODE-2938): add service host mechanism property
1 parent 323bb8d commit 747528b

File tree

10 files changed

+57
-15
lines changed

10 files changed

+57
-15
lines changed

src/cmap/auth/gssapi.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { AuthContext, AuthProvider } from './auth_provider';
1414

1515
type MechanismProperties = {
1616
gssapiCanonicalizeHostName?: boolean;
17+
SERVICE_HOST?: string;
1718
SERVICE_NAME?: string;
1819
SERVICE_REALM?: string;
1920
};
@@ -70,6 +71,7 @@ export class GSSAPI extends AuthProvider {
7071
});
7172
}
7273
}
74+
7375
function makeKerberosClient(authContext: AuthContext, callback: Callback<KerberosClient>): void {
7476
const { hostAddress } = authContext.options;
7577
const { credentials } = authContext;
@@ -100,7 +102,8 @@ function makeKerberosClient(authContext: AuthContext, callback: Callback<Kerbero
100102
Object.assign(initOptions, { user: username, password: password });
101103
}
102104

103-
let spn = `${serviceName}${process.platform === 'win32' ? '/' : '@'}${host}`;
105+
const spnHost = mechanismProperties.SERVICE_HOST ?? host;
106+
let spn = `${serviceName}${process.platform === 'win32' ? '/' : '@'}${spnHost}`;
104107
if ('SERVICE_REALM' in mechanismProperties) {
105108
spn = `${spn}@${mechanismProperties.SERVICE_REALM}`;
106109
}

src/cmap/auth/mongo_credentials.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function getDefaultAuthMechanism(hello?: Document): AuthMechanism {
2727

2828
/** @public */
2929
export interface AuthMechanismProperties extends Document {
30+
SERVICE_HOST?: string;
3031
SERVICE_NAME?: string;
3132
SERVICE_REALM?: string;
3233
CANONICALIZE_HOST_NAME?: boolean;

test/manual/kerberos.test.js

+32-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('Kerberos', function () {
2828
return;
2929
}
3030
let krb5Uri = process.env.MONGODB_URI;
31+
const parts = krb5Uri.split('@', 2);
3132

3233
if (!process.env.KRB5_PRINCIPAL) {
3334
console.error('skipping Kerberos tests, KRB5_PRINCIPAL environment variable is not defined');
@@ -39,7 +40,6 @@ describe('Kerberos', function () {
3940
if (process.env.LDAPTEST_PASSWORD == null) {
4041
throw new Error('The env parameter LDAPTEST_PASSWORD must be set');
4142
}
42-
const parts = krb5Uri.split('@', 2);
4343
krb5Uri = `${parts[0]}:${process.env.LDAPTEST_PASSWORD}@${parts[1]}`;
4444
}
4545

@@ -62,6 +62,37 @@ describe('Kerberos', function () {
6262
});
6363
});
6464

65+
context('when passsing SERVICE_HOST', function () {
66+
context('when the SERVICE_HOST is invalid', function () {
67+
const client = new MongoClient(`${krb5Uri}&maxPoolSize=1`, {
68+
authMechanismProperties: {
69+
SERVICE_HOST: 'example.com'
70+
}
71+
});
72+
73+
it('fails to authenticate', function () {
74+
return client.connect().catch(e => {
75+
expect(e).to.exist;
76+
});
77+
});
78+
});
79+
80+
context('when the SERVICE_HOST is valid', function () {
81+
const client = new MongoClient(`${krb5Uri}&maxPoolSize=1`, {
82+
authMechanismProperties: {
83+
SERVICE_HOST: 'ldaptest.10gen.cc'
84+
}
85+
});
86+
87+
it('authenticates', function (done) {
88+
client.connect(function (err, client) {
89+
expect(err).to.not.exist;
90+
verifyKerberosAuthentication(client, done);
91+
});
92+
});
93+
});
94+
});
95+
6596
describe('should use the SERVICE_NAME property', function () {
6697
it('as an option handed to the MongoClient', function (done) {
6798
const client = new MongoClient(`${krb5Uri}&maxPoolSize=1`, {

test/spec/auth/connection-string.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
},
8181
{
8282
"description": "should accept generic mechanism property (GSSAPI)",
83-
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true",
83+
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com",
8484
"valid": true,
8585
"credential": {
8686
"username": "[email protected]",
@@ -89,7 +89,8 @@
8989
"mechanism": "GSSAPI",
9090
"mechanism_properties": {
9191
"SERVICE_NAME": "other",
92-
"CANONICALIZE_HOST_NAME": true
92+
"CANONICALIZE_HOST_NAME": true,
93+
"SERVICE_HOST": "example.com"
9394
}
9495
}
9596
},
@@ -368,4 +369,4 @@
368369
"valid": false
369370
}
370371
]
371-
}
372+
}

test/spec/auth/connection-string.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ tests:
6464
SERVICE_NAME: "mongodb"
6565
-
6666
description: "should accept generic mechanism property (GSSAPI)"
67-
uri: "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true"
67+
uri: "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com"
6868
valid: true
6969
credential:
7070
username: "[email protected]"
@@ -74,6 +74,7 @@ tests:
7474
mechanism_properties:
7575
SERVICE_NAME: "other"
7676
CANONICALIZE_HOST_NAME: true
77+
SERVICE_HOST: "example.com"
7778
-
7879
description: "should accept the password (GSSAPI)"
7980
uri: "mongodb://user%40DOMAIN.COM:password@localhost/?authMechanism=GSSAPI&authSource=$external"

test/spec/connection-string/valid-auth.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@
263263
},
264264
{
265265
"description": "Escaped username (GSSAPI)",
266-
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI",
266+
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com&authMechanism=GSSAPI",
267267
"valid": true,
268268
"warning": false,
269269
"hosts": [
@@ -282,7 +282,8 @@
282282
"authmechanism": "GSSAPI",
283283
"authmechanismproperties": {
284284
"SERVICE_NAME": "other",
285-
"CANONICALIZE_HOST_NAME": true
285+
"CANONICALIZE_HOST_NAME": true,
286+
"SERVICE_HOST": "example.com"
286287
}
287288
}
288289
},

test/spec/connection-string/valid-auth.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ tests:
206206
authmechanism: "MONGODB-X509"
207207
-
208208
description: "Escaped username (GSSAPI)"
209-
uri: "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI"
209+
uri: "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com&authMechanism=GSSAPI"
210210
valid: true
211211
warning: false
212212
hosts:
@@ -222,7 +222,8 @@ tests:
222222
authmechanism: "GSSAPI"
223223
authmechanismproperties:
224224
SERVICE_NAME: "other"
225-
CANONICALIZE_HOST_NAME: true
225+
CANONICALIZE_HOST_NAME: true,
226+
SERVICE_HOST: "example.com"
226227
-
227228
description: "At-signs in options aren't part of the userinfo"
228229
uri: "mongodb://alice:[email protected]/admin?replicaset=my@replicaset"

test/spec/uri-options/auth-options.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"tests": [
33
{
44
"description": "Valid auth options are parsed correctly (GSSAPI)",
5-
"uri": "mongodb://foo:[email protected]/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authSource=$external",
5+
"uri": "mongodb://foo:[email protected]/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com&authSource=$external",
66
"valid": true,
77
"warning": false,
88
"hosts": null,
@@ -11,7 +11,8 @@
1111
"authMechanism": "GSSAPI",
1212
"authMechanismProperties": {
1313
"SERVICE_NAME": "other",
14-
"CANONICALIZE_HOST_NAME": true
14+
"CANONICALIZE_HOST_NAME": true,
15+
"SERVICE_HOST": "example.com"
1516
},
1617
"authSource": "$external"
1718
}

test/spec/uri-options/auth-options.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
tests:
22
-
33
description: "Valid auth options are parsed correctly (GSSAPI)"
4-
uri: "mongodb://foo:[email protected]/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authSource=$external"
4+
uri: "mongodb://foo:[email protected]/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com&authSource=$external"
55
valid: true
66
warning: false
77
hosts: ~
@@ -10,7 +10,8 @@ tests:
1010
authMechanism: "GSSAPI"
1111
authMechanismProperties:
1212
SERVICE_NAME: "other"
13-
CANONICALIZE_HOST_NAME: true
13+
CANONICALIZE_HOST_NAME: true,
14+
SERVICE_HOST: "example.com"
1415
authSource: "$external"
1516
-
1617
description: "Valid auth options are parsed correctly (SCRAM-SHA-1)"

test/unit/connection_string.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ describe('Connection String', function () {
7777

7878
it('should parse `authMechanismProperties`', function () {
7979
const options = parseOptions(
80-
'mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,SERVICE_REALM:blah,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI'
80+
'mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,SERVICE_REALM:blah,CANONICALIZE_HOST_NAME:true,SERVICE_HOST:example.com&authMechanism=GSSAPI'
8181
);
8282
expect(options.credentials.mechanismProperties).to.deep.include({
83+
SERVICE_HOST: 'example.com',
8384
SERVICE_NAME: 'other',
8485
SERVICE_REALM: 'blah',
8586
CANONICALIZE_HOST_NAME: true

0 commit comments

Comments
 (0)