mongodb 5.0.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -22
- package/lib/bson.js +3 -1
- package/lib/bson.js.map +1 -1
- package/lib/change_stream.js +3 -2
- package/lib/change_stream.js.map +1 -1
- package/lib/cmap/auth/auth_provider.js +21 -10
- package/lib/cmap/auth/auth_provider.js.map +1 -1
- package/lib/cmap/auth/gssapi.js +71 -116
- package/lib/cmap/auth/gssapi.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js +17 -0
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongocr.js +20 -29
- package/lib/cmap/auth/mongocr.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js +126 -140
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js +28 -0
- package/lib/cmap/auth/mongodb_oidc/aws_service_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +178 -0
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js +41 -0
- package/lib/cmap/auth/mongodb_oidc/service_workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js +115 -0
- package/lib/cmap/auth/mongodb_oidc/token_entry_cache.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc/workflow.js +3 -0
- package/lib/cmap/auth/mongodb_oidc/workflow.js.map +1 -0
- package/lib/cmap/auth/mongodb_oidc.js +62 -0
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -0
- package/lib/cmap/auth/plain.js +4 -5
- package/lib/cmap/auth/plain.js.map +1 -1
- package/lib/cmap/auth/providers.js +4 -1
- package/lib/cmap/auth/providers.js.map +1 -1
- package/lib/cmap/auth/scram.js +45 -73
- package/lib/cmap/auth/scram.js.map +1 -1
- package/lib/cmap/auth/x509.js +8 -11
- package/lib/cmap/auth/x509.js.map +1 -1
- package/lib/cmap/command_monitoring_events.js +8 -5
- package/lib/cmap/command_monitoring_events.js.map +1 -1
- package/lib/cmap/commands.js +9 -1
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connect.js +72 -86
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +68 -74
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +51 -13
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/message_stream.js.map +1 -1
- package/lib/cmap/wire_protocol/shared.js +1 -16
- package/lib/cmap/wire_protocol/shared.js.map +1 -1
- package/lib/collection.js +10 -10
- package/lib/connection_string.js +47 -33
- package/lib/connection_string.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +13 -7
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +1 -1
- package/lib/db.js +3 -2
- package/lib/db.js.map +1 -1
- package/lib/error.js +2 -1
- package/lib/error.js.map +1 -1
- package/lib/mongo_client.js +22 -2
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_logger.js +17 -1
- package/lib/mongo_logger.js.map +1 -1
- package/lib/operations/aggregate.js +4 -1
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/create_collection.js +1 -0
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/execute_operation.js +8 -27
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js +3 -2
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/indexes.js +2 -1
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/list_collections.js +2 -1
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/read_concern.js +1 -1
- package/lib/read_preference.js +2 -2
- package/lib/sdam/monitor.js +1 -0
- package/lib/sdam/monitor.js.map +1 -1
- package/lib/sdam/server.js +4 -2
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/topology.js +3 -26
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +2 -1
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +15 -70
- package/lib/utils.js.map +1 -1
- package/lib/write_concern.js +1 -1
- package/mongodb.d.ts +137 -68
- package/package.json +30 -30
- package/src/bson.ts +3 -1
- package/src/bulk/common.ts +1 -1
- package/src/change_stream.ts +16 -8
- package/src/cmap/auth/auth_provider.ts +29 -16
- package/src/cmap/auth/gssapi.ts +102 -149
- package/src/cmap/auth/mongo_credentials.ts +47 -1
- package/src/cmap/auth/mongocr.ts +31 -36
- package/src/cmap/auth/mongodb_aws.ts +167 -189
- package/src/cmap/auth/mongodb_oidc/aws_service_workflow.ts +26 -0
- package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +259 -0
- package/src/cmap/auth/mongodb_oidc/service_workflow.ts +47 -0
- package/src/cmap/auth/mongodb_oidc/token_entry_cache.ts +166 -0
- package/src/cmap/auth/mongodb_oidc/workflow.ts +21 -0
- package/src/cmap/auth/mongodb_oidc.ts +123 -0
- package/src/cmap/auth/plain.ts +6 -6
- package/src/cmap/auth/providers.ts +5 -2
- package/src/cmap/auth/scram.ts +56 -90
- package/src/cmap/auth/x509.ts +12 -18
- package/src/cmap/command_monitoring_events.ts +5 -2
- package/src/cmap/commands.ts +11 -1
- package/src/cmap/connect.ts +90 -114
- package/src/cmap/connection.ts +92 -90
- package/src/cmap/connection_pool.ts +77 -16
- package/src/cmap/message_stream.ts +0 -2
- package/src/cmap/wire_protocol/compression.ts +1 -1
- package/src/cmap/wire_protocol/shared.ts +1 -23
- package/src/collection.ts +11 -11
- package/src/connection_string.ts +52 -35
- package/src/cursor/abstract_cursor.ts +13 -6
- package/src/cursor/change_stream_cursor.ts +5 -5
- package/src/cursor/find_cursor.ts +1 -1
- package/src/db.ts +3 -2
- package/src/deps.ts +56 -38
- package/src/error.ts +3 -2
- package/src/index.ts +7 -0
- package/src/mongo_client.ts +35 -10
- package/src/mongo_logger.ts +20 -2
- package/src/mongo_types.ts +4 -3
- package/src/operations/aggregate.ts +4 -2
- package/src/operations/create_collection.ts +2 -1
- package/src/operations/execute_operation.ts +8 -25
- package/src/operations/find.ts +13 -4
- package/src/operations/find_and_modify.ts +4 -4
- package/src/operations/indexes.ts +12 -4
- package/src/operations/list_collections.ts +11 -3
- package/src/operations/set_profiling_level.ts +1 -1
- package/src/operations/stats.ts +1 -1
- package/src/read_concern.ts +2 -2
- package/src/read_preference.ts +3 -3
- package/src/sdam/common.ts +2 -2
- package/src/sdam/monitor.ts +1 -0
- package/src/sdam/server.ts +4 -1
- package/src/sdam/topology.ts +4 -33
- package/src/sessions.ts +2 -1
- package/src/transactions.ts +1 -1
- package/src/utils.ts +24 -98
- package/src/write_concern.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongodb",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "The official MongoDB driver for Node.js",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"email": "dbx-node@mongodb.com"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"bson": "^5.
|
|
28
|
+
"bson": "^5.2.0",
|
|
29
29
|
"mongodb-connection-string-url": "^2.6.0",
|
|
30
30
|
"socks": "^2.7.1"
|
|
31
31
|
},
|
|
@@ -49,54 +49,53 @@
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@aws-sdk/credential-providers": "^3.201.0",
|
|
53
52
|
"@iarna/toml": "^2.2.5",
|
|
54
53
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
55
|
-
"@microsoft/api-extractor": "^7.
|
|
54
|
+
"@microsoft/api-extractor": "^7.34.4",
|
|
56
55
|
"@microsoft/tsdoc-config": "^0.16.2",
|
|
57
|
-
"@mongodb-js/zstd": "^1.
|
|
58
|
-
"@types/chai": "^4.3.
|
|
56
|
+
"@mongodb-js/zstd": "^1.1.0",
|
|
57
|
+
"@types/chai": "^4.3.4",
|
|
59
58
|
"@types/chai-subset": "^1.3.3",
|
|
60
|
-
"@types/express": "^4.17.
|
|
59
|
+
"@types/express": "^4.17.17",
|
|
61
60
|
"@types/kerberos": "^1.1.1",
|
|
62
|
-
"@types/mocha": "^10.0.
|
|
63
|
-
"@types/node": "^18.11.
|
|
61
|
+
"@types/mocha": "^10.0.1",
|
|
62
|
+
"@types/node": "^18.11.19",
|
|
64
63
|
"@types/saslprep": "^1.0.1",
|
|
65
|
-
"@types/semver": "^7.3.
|
|
64
|
+
"@types/semver": "^7.3.13",
|
|
66
65
|
"@types/sinon": "^10.0.13",
|
|
67
|
-
"@types/sinon-chai": "^3.2.
|
|
66
|
+
"@types/sinon-chai": "^3.2.9",
|
|
68
67
|
"@types/whatwg-url": "^11.0.0",
|
|
69
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
70
|
-
"@typescript-eslint/parser": "^5.
|
|
71
|
-
"chai": "^4.3.
|
|
68
|
+
"@typescript-eslint/eslint-plugin": "^5.55.0",
|
|
69
|
+
"@typescript-eslint/parser": "^5.55.0",
|
|
70
|
+
"chai": "^4.3.7",
|
|
72
71
|
"chai-subset": "^1.6.0",
|
|
73
72
|
"chalk": "^4.1.2",
|
|
74
|
-
"eslint": "^8.
|
|
75
|
-
"eslint-config-prettier": "^8.
|
|
76
|
-
"eslint-plugin-import": "^2.
|
|
73
|
+
"eslint": "^8.36.0",
|
|
74
|
+
"eslint-config-prettier": "^8.7.0",
|
|
75
|
+
"eslint-plugin-import": "^2.27.5",
|
|
77
76
|
"eslint-plugin-prettier": "^4.2.1",
|
|
78
|
-
"eslint-plugin-simple-import-sort": "^
|
|
77
|
+
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
79
78
|
"eslint-plugin-tsdoc": "^0.2.17",
|
|
80
79
|
"express": "^4.18.2",
|
|
81
80
|
"js-yaml": "^4.1.0",
|
|
82
|
-
"mocha": "^
|
|
81
|
+
"mocha": "^10.2.0",
|
|
83
82
|
"mocha-sinon": "^2.1.2",
|
|
84
|
-
"mongodb-legacy": "^
|
|
83
|
+
"mongodb-legacy": "^5.0.0",
|
|
85
84
|
"nyc": "^15.1.0",
|
|
86
|
-
"prettier": "^2.
|
|
87
|
-
"rimraf": "^3.0.2",
|
|
85
|
+
"prettier": "^2.8.4",
|
|
88
86
|
"semver": "^7.3.8",
|
|
89
|
-
"sinon": "^
|
|
87
|
+
"sinon": "^15.0.2",
|
|
90
88
|
"sinon-chai": "^3.7.0",
|
|
91
89
|
"snappy": "^7.2.2",
|
|
92
90
|
"source-map-support": "^0.5.21",
|
|
93
91
|
"standard-version": "^9.5.0",
|
|
94
92
|
"ts-node": "^10.9.1",
|
|
95
|
-
"tsd": "^0.
|
|
96
|
-
"typescript": "^4.9.
|
|
93
|
+
"tsd": "^0.27.0",
|
|
94
|
+
"typescript": "^4.9.5",
|
|
97
95
|
"typescript-cached-transpile": "^0.0.6",
|
|
96
|
+
"v8-heapsnapshot": "^1.2.0",
|
|
98
97
|
"xml2js": "^0.4.23",
|
|
99
|
-
"yargs": "^17.
|
|
98
|
+
"yargs": "^17.7.1"
|
|
100
99
|
},
|
|
101
100
|
"license": "Apache-2.0",
|
|
102
101
|
"engines": {
|
|
@@ -109,7 +108,7 @@
|
|
|
109
108
|
"scripts": {
|
|
110
109
|
"build:evergreen": "node .evergreen/generate_evergreen_tasks.js",
|
|
111
110
|
"build:ts": "node ./node_modules/typescript/bin/tsc",
|
|
112
|
-
"build:dts": "npm run build:ts && api-extractor run &&
|
|
111
|
+
"build:dts": "npm run build:ts && api-extractor run && node etc/clean_definition_files.cjs",
|
|
113
112
|
"build:docs": "./etc/docs/build.ts",
|
|
114
113
|
"build:typedoc": "typedoc",
|
|
115
114
|
"check:bench": "node test/benchmarks/driverBench",
|
|
@@ -127,11 +126,12 @@
|
|
|
127
126
|
"check:ts": "node ./node_modules/typescript/bin/tsc -v && node ./node_modules/typescript/bin/tsc --noEmit",
|
|
128
127
|
"check:atlas": "mocha --config test/manual/mocharc.json test/manual/atlas_connectivity.test.js",
|
|
129
128
|
"check:adl": "mocha --config test/mocha_mongodb.json test/manual/atlas-data-lake-testing",
|
|
130
|
-
"check:aws": "mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_aws.test.ts",
|
|
129
|
+
"check:aws": "nyc mocha --config test/mocha_mongodb.json test/integration/auth/mongodb_aws.test.ts",
|
|
130
|
+
"check:oidc": "mocha --config test/manual/mocharc.json test/manual/mongodb_oidc.prose.test.ts",
|
|
131
131
|
"check:ocsp": "mocha --config test/manual/mocharc.json test/manual/ocsp_support.test.js",
|
|
132
|
-
"check:kerberos": "mocha --config test/manual/mocharc.json test/manual/kerberos.test.
|
|
132
|
+
"check:kerberos": "nyc mocha --config test/manual/mocharc.json test/manual/kerberos.test.ts",
|
|
133
133
|
"check:tls": "mocha --config test/manual/mocharc.json test/manual/tls_support.test.js",
|
|
134
|
-
"check:ldap": "mocha --config test/manual/mocharc.json test/manual/ldap.test.js",
|
|
134
|
+
"check:ldap": "nyc mocha --config test/manual/mocharc.json test/manual/ldap.test.js",
|
|
135
135
|
"check:socks5": "mocha --config test/manual/mocharc.json test/manual/socks5.test.ts",
|
|
136
136
|
"check:csfle": "mocha --config test/mocha_mongodb.json test/integration/client-side-encryption",
|
|
137
137
|
"check:snappy": "mocha test/unit/assorted/snappy.test.js",
|
package/src/bson.ts
CHANGED
|
@@ -36,7 +36,6 @@ export interface BSONSerializeOptions
|
|
|
36
36
|
| 'allowObjectSmallerThanBufferSize'
|
|
37
37
|
| 'index'
|
|
38
38
|
| 'validation'
|
|
39
|
-
| 'useBigInt64'
|
|
40
39
|
> {
|
|
41
40
|
/**
|
|
42
41
|
* Enabling the raw option will return a [Node.js Buffer](https://nodejs.org/api/buffer.html)
|
|
@@ -67,6 +66,7 @@ export interface BSONSerializeOptions
|
|
|
67
66
|
export function pluckBSONSerializeOptions(options: BSONSerializeOptions): BSONSerializeOptions {
|
|
68
67
|
const {
|
|
69
68
|
fieldsAsRaw,
|
|
69
|
+
useBigInt64,
|
|
70
70
|
promoteValues,
|
|
71
71
|
promoteBuffers,
|
|
72
72
|
promoteLongs,
|
|
@@ -78,6 +78,7 @@ export function pluckBSONSerializeOptions(options: BSONSerializeOptions): BSONSe
|
|
|
78
78
|
} = options;
|
|
79
79
|
return {
|
|
80
80
|
fieldsAsRaw,
|
|
81
|
+
useBigInt64,
|
|
81
82
|
promoteValues,
|
|
82
83
|
promoteBuffers,
|
|
83
84
|
promoteLongs,
|
|
@@ -102,6 +103,7 @@ export function resolveBSONOptions(
|
|
|
102
103
|
const parentOptions = parent?.bsonOptions;
|
|
103
104
|
return {
|
|
104
105
|
raw: options?.raw ?? parentOptions?.raw ?? false,
|
|
106
|
+
useBigInt64: options?.useBigInt64 ?? parentOptions?.useBigInt64 ?? false,
|
|
105
107
|
promoteLongs: options?.promoteLongs ?? parentOptions?.promoteLongs ?? true,
|
|
106
108
|
promoteValues: options?.promoteValues ?? parentOptions?.promoteValues ?? true,
|
|
107
109
|
promoteBuffers: options?.promoteBuffers ?? parentOptions?.promoteBuffers ?? false,
|
package/src/bulk/common.ts
CHANGED
|
@@ -39,7 +39,7 @@ export const BatchType = Object.freeze({
|
|
|
39
39
|
} as const);
|
|
40
40
|
|
|
41
41
|
/** @public */
|
|
42
|
-
export type BatchType = typeof BatchType[keyof typeof BatchType];
|
|
42
|
+
export type BatchType = (typeof BatchType)[keyof typeof BatchType];
|
|
43
43
|
|
|
44
44
|
/** @public */
|
|
45
45
|
export interface InsertOneModel<TSchema extends Document = Document> {
|
package/src/change_stream.ts
CHANGED
|
@@ -74,7 +74,7 @@ export type ResumeToken = unknown;
|
|
|
74
74
|
/**
|
|
75
75
|
* Represents a specific point in time on a server. Can be retrieved by using `db.command()`
|
|
76
76
|
* @public
|
|
77
|
-
* @see https://
|
|
77
|
+
* @see https://www.mongodb.com/docs/manual/reference/method/db.runCommand/#response
|
|
78
78
|
*/
|
|
79
79
|
export type OperationTime = Timestamp;
|
|
80
80
|
|
|
@@ -82,7 +82,7 @@ export type OperationTime = Timestamp;
|
|
|
82
82
|
* Options that can be passed to a ChangeStream. Note that startAfter, resumeAfter, and startAtOperationTime are all mutually exclusive, and the server will error if more than one is specified.
|
|
83
83
|
* @public
|
|
84
84
|
*/
|
|
85
|
-
export interface ChangeStreamOptions extends AggregateOptions {
|
|
85
|
+
export interface ChangeStreamOptions extends Omit<AggregateOptions, 'writeConcern'> {
|
|
86
86
|
/**
|
|
87
87
|
* Allowed values: 'updateLookup', 'whenAvailable', 'required'.
|
|
88
88
|
*
|
|
@@ -117,19 +117,19 @@ export interface ChangeStreamOptions extends AggregateOptions {
|
|
|
117
117
|
maxAwaitTimeMS?: number;
|
|
118
118
|
/**
|
|
119
119
|
* Allows you to start a changeStream after a specified event.
|
|
120
|
-
* @see https://
|
|
120
|
+
* @see https://www.mongodb.com/docs/manual/changeStreams/#resumeafter-for-change-streams
|
|
121
121
|
*/
|
|
122
122
|
resumeAfter?: ResumeToken;
|
|
123
123
|
/**
|
|
124
124
|
* Similar to resumeAfter, but will allow you to start after an invalidated event.
|
|
125
|
-
* @see https://
|
|
125
|
+
* @see https://www.mongodb.com/docs/manual/changeStreams/#startafter-for-change-streams
|
|
126
126
|
*/
|
|
127
127
|
startAfter?: ResumeToken;
|
|
128
128
|
/** Will start the changeStream after the specified operationTime. */
|
|
129
129
|
startAtOperationTime?: OperationTime;
|
|
130
130
|
/**
|
|
131
131
|
* The number of documents to return per batch.
|
|
132
|
-
* @see https://
|
|
132
|
+
* @see https://www.mongodb.com/docs/manual/reference/command/aggregate
|
|
133
133
|
*/
|
|
134
134
|
batchSize?: number;
|
|
135
135
|
|
|
@@ -533,7 +533,14 @@ export class ChangeStream<
|
|
|
533
533
|
TChange extends Document = ChangeStreamDocument<TSchema>
|
|
534
534
|
> extends TypedEventEmitter<ChangeStreamEvents<TSchema, TChange>> {
|
|
535
535
|
pipeline: Document[];
|
|
536
|
-
|
|
536
|
+
/**
|
|
537
|
+
* @remarks WriteConcern can still be present on the options because
|
|
538
|
+
* we inherit options from the client/db/collection. The
|
|
539
|
+
* key must be present on the options in order to delete it.
|
|
540
|
+
* This allows typescript to delete the key but will
|
|
541
|
+
* not allow a writeConcern to be assigned as a property on options.
|
|
542
|
+
*/
|
|
543
|
+
options: ChangeStreamOptions & { writeConcern?: never };
|
|
537
544
|
parent: MongoClient | Db | Collection;
|
|
538
545
|
namespace: MongoDBNamespace;
|
|
539
546
|
type: symbol;
|
|
@@ -576,7 +583,7 @@ export class ChangeStream<
|
|
|
576
583
|
* @internal
|
|
577
584
|
*
|
|
578
585
|
* @param parent - The parent object that created this change stream
|
|
579
|
-
* @param pipeline - An array of {@link https://
|
|
586
|
+
* @param pipeline - An array of {@link https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/|aggregation pipeline stages} through which to pass change stream documents
|
|
580
587
|
*/
|
|
581
588
|
constructor(
|
|
582
589
|
parent: OperationParent,
|
|
@@ -586,7 +593,8 @@ export class ChangeStream<
|
|
|
586
593
|
super();
|
|
587
594
|
|
|
588
595
|
this.pipeline = pipeline;
|
|
589
|
-
this.options = options;
|
|
596
|
+
this.options = { ...options };
|
|
597
|
+
delete this.options.writeConcern;
|
|
590
598
|
|
|
591
599
|
if (parent instanceof Collection) {
|
|
592
600
|
this.type = CHANGE_DOMAIN_TYPES.COLLECTION;
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import type { Document } from '../../bson';
|
|
2
2
|
import { MongoRuntimeError } from '../../error';
|
|
3
|
-
import type { Callback, ClientMetadataOptions } from '../../utils';
|
|
4
3
|
import type { HandshakeDocument } from '../connect';
|
|
5
4
|
import type { Connection, ConnectionOptions } from '../connection';
|
|
6
5
|
import type { MongoCredentials } from './mongo_credentials';
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Context used during authentication
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
11
|
export class AuthContext {
|
|
12
12
|
/** The connection to authenticate */
|
|
13
13
|
connection: Connection;
|
|
14
14
|
/** The credentials to use for authentication */
|
|
15
15
|
credentials?: MongoCredentials;
|
|
16
|
+
/** If the context is for reauthentication. */
|
|
17
|
+
reauthenticating = false;
|
|
16
18
|
/** The options passed to the `connect` method */
|
|
17
|
-
options:
|
|
19
|
+
options: ConnectionOptions;
|
|
18
20
|
|
|
19
21
|
/** A response from an initial auth attempt, only some mechanisms use this (e.g, SCRAM) */
|
|
20
22
|
response?: Document;
|
|
@@ -24,7 +26,7 @@ export class AuthContext {
|
|
|
24
26
|
constructor(
|
|
25
27
|
connection: Connection,
|
|
26
28
|
credentials: MongoCredentials | undefined,
|
|
27
|
-
options:
|
|
29
|
+
options: ConnectionOptions
|
|
28
30
|
) {
|
|
29
31
|
this.connection = connection;
|
|
30
32
|
this.credentials = credentials;
|
|
@@ -32,29 +34,40 @@ export class AuthContext {
|
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
export class AuthProvider {
|
|
37
|
+
export abstract class AuthProvider {
|
|
36
38
|
/**
|
|
37
39
|
* Prepare the handshake document before the initial handshake.
|
|
38
40
|
*
|
|
39
41
|
* @param handshakeDoc - The document used for the initial handshake on a connection
|
|
40
42
|
* @param authContext - Context for authentication flow
|
|
41
43
|
*/
|
|
42
|
-
prepare(
|
|
44
|
+
async prepare(
|
|
43
45
|
handshakeDoc: HandshakeDocument,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
callback(undefined, handshakeDoc);
|
|
46
|
+
_authContext: AuthContext
|
|
47
|
+
): Promise<HandshakeDocument> {
|
|
48
|
+
return handshakeDoc;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Authenticate
|
|
52
53
|
*
|
|
53
54
|
* @param context - A shared context for authentication flow
|
|
54
|
-
* @param callback - The callback to return the result from the authentication
|
|
55
55
|
*/
|
|
56
|
-
auth(context: AuthContext
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
abstract auth(context: AuthContext): Promise<void>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Reauthenticate.
|
|
60
|
+
* @param context - The shared auth context.
|
|
61
|
+
*/
|
|
62
|
+
async reauth(context: AuthContext): Promise<void> {
|
|
63
|
+
if (context.reauthenticating) {
|
|
64
|
+
throw new MongoRuntimeError('Reauthentication already in progress.');
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
context.reauthenticating = true;
|
|
68
|
+
await this.auth(context);
|
|
69
|
+
} finally {
|
|
70
|
+
context.reauthenticating = false;
|
|
71
|
+
}
|
|
59
72
|
}
|
|
60
73
|
}
|
package/src/cmap/auth/gssapi.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import * as dns from 'dns';
|
|
2
2
|
|
|
3
|
-
import type { Document } from '../../bson';
|
|
4
3
|
import { Kerberos, KerberosClient } from '../../deps';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
MongoMissingCredentialsError,
|
|
9
|
-
MongoMissingDependencyError,
|
|
10
|
-
MongoRuntimeError
|
|
11
|
-
} from '../../error';
|
|
12
|
-
import { Callback, ns } from '../../utils';
|
|
4
|
+
import { MongoInvalidArgumentError, MongoMissingCredentialsError } from '../../error';
|
|
5
|
+
import { ns } from '../../utils';
|
|
6
|
+
import type { Connection } from '../connection';
|
|
13
7
|
import { AuthContext, AuthProvider } from './auth_provider';
|
|
14
8
|
|
|
15
9
|
/** @public */
|
|
@@ -23,7 +17,7 @@ export const GSSAPICanonicalizationValue = Object.freeze({
|
|
|
23
17
|
|
|
24
18
|
/** @public */
|
|
25
19
|
export type GSSAPICanonicalizationValue =
|
|
26
|
-
typeof GSSAPICanonicalizationValue[keyof typeof GSSAPICanonicalizationValue];
|
|
20
|
+
(typeof GSSAPICanonicalizationValue)[keyof typeof GSSAPICanonicalizationValue];
|
|
27
21
|
|
|
28
22
|
type MechanismProperties = {
|
|
29
23
|
CANONICALIZE_HOST_NAME?: GSSAPICanonicalizationValue;
|
|
@@ -32,70 +26,59 @@ type MechanismProperties = {
|
|
|
32
26
|
SERVICE_REALM?: string;
|
|
33
27
|
};
|
|
34
28
|
|
|
29
|
+
async function externalCommand(
|
|
30
|
+
connection: Connection,
|
|
31
|
+
command: ReturnType<typeof saslStart> | ReturnType<typeof saslContinue>
|
|
32
|
+
): Promise<{ payload: string; conversationId: any }> {
|
|
33
|
+
return connection.commandAsync(ns('$external.$cmd'), command, undefined) as Promise<{
|
|
34
|
+
payload: string;
|
|
35
|
+
conversationId: any;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
|
|
35
39
|
export class GSSAPI extends AuthProvider {
|
|
36
|
-
override auth(authContext: AuthContext
|
|
40
|
+
override async auth(authContext: AuthContext): Promise<void> {
|
|
37
41
|
const { connection, credentials } = authContext;
|
|
38
|
-
if (credentials == null)
|
|
39
|
-
|
|
40
|
-
new MongoMissingCredentialsError('Credentials required for GSSAPI authentication')
|
|
41
|
-
);
|
|
42
|
-
const { username } = credentials;
|
|
43
|
-
function externalCommand(
|
|
44
|
-
command: Document,
|
|
45
|
-
cb: Callback<{ payload: string; conversationId: any }>
|
|
46
|
-
) {
|
|
47
|
-
return connection.command(ns('$external.$cmd'), command, undefined, cb);
|
|
42
|
+
if (credentials == null) {
|
|
43
|
+
throw new MongoMissingCredentialsError('Credentials required for GSSAPI authentication');
|
|
48
44
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
payload
|
|
72
|
-
},
|
|
73
|
-
(err, result) => {
|
|
74
|
-
if (err) return callback(err);
|
|
75
|
-
|
|
76
|
-
callback(undefined, result);
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
});
|
|
45
|
+
|
|
46
|
+
const { username } = credentials;
|
|
47
|
+
|
|
48
|
+
const client = await makeKerberosClient(authContext);
|
|
49
|
+
|
|
50
|
+
const payload = await client.step('');
|
|
51
|
+
|
|
52
|
+
const saslStartResponse = await externalCommand(connection, saslStart(payload));
|
|
53
|
+
|
|
54
|
+
const negotiatedPayload = await negotiate(client, 10, saslStartResponse.payload);
|
|
55
|
+
|
|
56
|
+
const saslContinueResponse = await externalCommand(
|
|
57
|
+
connection,
|
|
58
|
+
saslContinue(negotiatedPayload, saslStartResponse.conversationId)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const finalizePayload = await finalize(client, username, saslContinueResponse.payload);
|
|
62
|
+
|
|
63
|
+
await externalCommand(connection, {
|
|
64
|
+
saslContinue: 1,
|
|
65
|
+
conversationId: saslContinueResponse.conversationId,
|
|
66
|
+
payload: finalizePayload
|
|
84
67
|
});
|
|
85
68
|
}
|
|
86
69
|
}
|
|
87
70
|
|
|
88
|
-
function makeKerberosClient(authContext: AuthContext
|
|
71
|
+
async function makeKerberosClient(authContext: AuthContext): Promise<KerberosClient> {
|
|
89
72
|
const { hostAddress } = authContext.options;
|
|
90
73
|
const { credentials } = authContext;
|
|
91
74
|
if (!hostAddress || typeof hostAddress.host !== 'string' || !credentials) {
|
|
92
|
-
|
|
93
|
-
|
|
75
|
+
throw new MongoInvalidArgumentError(
|
|
76
|
+
'Connection must have host and port and credentials defined.'
|
|
94
77
|
);
|
|
95
78
|
}
|
|
96
79
|
|
|
97
80
|
if ('kModuleError' in Kerberos) {
|
|
98
|
-
|
|
81
|
+
throw Kerberos['kModuleError'];
|
|
99
82
|
}
|
|
100
83
|
const { initializeClient } = Kerberos;
|
|
101
84
|
|
|
@@ -104,95 +87,71 @@ function makeKerberosClient(authContext: AuthContext, callback: Callback<Kerbero
|
|
|
104
87
|
|
|
105
88
|
const serviceName = mechanismProperties.SERVICE_NAME ?? 'mongodb';
|
|
106
89
|
|
|
107
|
-
performGSSAPICanonicalizeHostName(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
initializeClient(spn, initOptions, (err: string, client: KerberosClient): void => {
|
|
125
|
-
// TODO(NODE-3483)
|
|
126
|
-
if (err) return callback(new MongoRuntimeError(err));
|
|
127
|
-
callback(undefined, client);
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
);
|
|
90
|
+
const host = await performGSSAPICanonicalizeHostName(hostAddress.host, mechanismProperties);
|
|
91
|
+
|
|
92
|
+
const initOptions = {};
|
|
93
|
+
if (password != null) {
|
|
94
|
+
// TODO(NODE-5139): These do not match the typescript options in initializeClient
|
|
95
|
+
Object.assign(initOptions, { user: username, password: password });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const spnHost = mechanismProperties.SERVICE_HOST ?? host;
|
|
99
|
+
let spn = `${serviceName}${process.platform === 'win32' ? '/' : '@'}${spnHost}`;
|
|
100
|
+
if ('SERVICE_REALM' in mechanismProperties) {
|
|
101
|
+
spn = `${spn}@${mechanismProperties.SERVICE_REALM}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return initializeClient(spn, initOptions);
|
|
131
105
|
}
|
|
132
106
|
|
|
133
|
-
function saslStart(payload
|
|
107
|
+
function saslStart(payload: string) {
|
|
134
108
|
return {
|
|
135
109
|
saslStart: 1,
|
|
136
110
|
mechanism: 'GSSAPI',
|
|
137
111
|
payload,
|
|
138
112
|
autoAuthorize: 1
|
|
139
|
-
};
|
|
113
|
+
} as const;
|
|
140
114
|
}
|
|
141
115
|
|
|
142
|
-
function saslContinue(payload
|
|
116
|
+
function saslContinue(payload: string, conversationId: number) {
|
|
143
117
|
return {
|
|
144
118
|
saslContinue: 1,
|
|
145
119
|
conversationId,
|
|
146
120
|
payload
|
|
147
|
-
};
|
|
121
|
+
} as const;
|
|
148
122
|
}
|
|
149
123
|
|
|
150
|
-
function negotiate(
|
|
124
|
+
async function negotiate(
|
|
151
125
|
client: KerberosClient,
|
|
152
126
|
retries: number,
|
|
153
|
-
payload: string
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
127
|
+
payload: string
|
|
128
|
+
): Promise<string> {
|
|
129
|
+
try {
|
|
130
|
+
const response = await client.step(payload);
|
|
131
|
+
return response || '';
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (retries === 0) {
|
|
134
|
+
// Retries exhausted, raise error
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
160
137
|
// Adjust number of retries and call step again
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// Return the payload
|
|
164
|
-
callback(undefined, response || '');
|
|
165
|
-
});
|
|
138
|
+
return negotiate(client, retries - 1, payload);
|
|
139
|
+
}
|
|
166
140
|
}
|
|
167
141
|
|
|
168
|
-
function finalize(
|
|
169
|
-
client: KerberosClient,
|
|
170
|
-
user: string,
|
|
171
|
-
payload: string,
|
|
172
|
-
callback: Callback<string>
|
|
173
|
-
): void {
|
|
142
|
+
async function finalize(client: KerberosClient, user: string, payload: string): Promise<string> {
|
|
174
143
|
// GSS Client Unwrap
|
|
175
|
-
client.unwrap(payload
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// Wrap the response
|
|
179
|
-
client.wrap(response || '', { user }, (err, wrapped) => {
|
|
180
|
-
if (err) return callback(err);
|
|
181
|
-
|
|
182
|
-
// Return the payload
|
|
183
|
-
callback(undefined, wrapped);
|
|
184
|
-
});
|
|
185
|
-
});
|
|
144
|
+
const response = await client.unwrap(payload);
|
|
145
|
+
return client.wrap(response || '', { user });
|
|
186
146
|
}
|
|
187
147
|
|
|
188
|
-
export function performGSSAPICanonicalizeHostName(
|
|
148
|
+
export async function performGSSAPICanonicalizeHostName(
|
|
189
149
|
host: string,
|
|
190
|
-
mechanismProperties: MechanismProperties
|
|
191
|
-
|
|
192
|
-
): void {
|
|
150
|
+
mechanismProperties: MechanismProperties
|
|
151
|
+
): Promise<string> {
|
|
193
152
|
const mode = mechanismProperties.CANONICALIZE_HOST_NAME;
|
|
194
153
|
if (!mode || mode === GSSAPICanonicalizationValue.none) {
|
|
195
|
-
return
|
|
154
|
+
return host;
|
|
196
155
|
}
|
|
197
156
|
|
|
198
157
|
// If forward and reverse or true
|
|
@@ -201,39 +160,33 @@ export function performGSSAPICanonicalizeHostName(
|
|
|
201
160
|
mode === GSSAPICanonicalizationValue.forwardAndReverse
|
|
202
161
|
) {
|
|
203
162
|
// Perform the lookup of the ip address.
|
|
204
|
-
dns.lookup(host
|
|
205
|
-
// No ip found, return the error.
|
|
206
|
-
if (error) return callback(error);
|
|
163
|
+
const { address } = await dns.promises.lookup(host);
|
|
207
164
|
|
|
165
|
+
try {
|
|
208
166
|
// Perform a reverse ptr lookup on the ip address.
|
|
209
|
-
dns.resolvePtr(address
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
});
|
|
219
|
-
});
|
|
167
|
+
const results = await dns.promises.resolvePtr(address);
|
|
168
|
+
// If the ptr did not error but had no results, return the host.
|
|
169
|
+
return results.length > 0 ? results[0] : host;
|
|
170
|
+
} catch (error) {
|
|
171
|
+
// This can error as ptr records may not exist for all ips. In this case
|
|
172
|
+
// fallback to a cname lookup as dns.lookup() does not return the
|
|
173
|
+
// cname.
|
|
174
|
+
return resolveCname(host);
|
|
175
|
+
}
|
|
220
176
|
} else {
|
|
221
177
|
// The case for forward is just to resolve the cname as dns.lookup()
|
|
222
178
|
// will not return it.
|
|
223
|
-
resolveCname(host
|
|
179
|
+
return resolveCname(host);
|
|
224
180
|
}
|
|
225
181
|
}
|
|
226
182
|
|
|
227
|
-
export function resolveCname(host: string
|
|
183
|
+
export async function resolveCname(host: string): Promise<string> {
|
|
228
184
|
// Attempt to resolve the host name
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
callback(undefined, host);
|
|
238
|
-
});
|
|
185
|
+
try {
|
|
186
|
+
const results = await dns.promises.resolveCname(host);
|
|
187
|
+
// Get the first resolved host id
|
|
188
|
+
return results.length > 0 ? results[0] : host;
|
|
189
|
+
} catch {
|
|
190
|
+
return host;
|
|
191
|
+
}
|
|
239
192
|
}
|