-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathx509_auth.test.ts
More file actions
132 lines (116 loc) · 4.23 KB
/
x509_auth.test.ts
File metadata and controls
132 lines (116 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { expect } from 'chai';
import { ConnectionString } from 'mongodb-connection-string-url';
import {
MongoClient,
type MongoClientOptions,
MongoServerError,
MongoServerSelectionError
} from '../../src';
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const connectionString = new ConnectionString(process.env.MONGODB_URI!);
describe('x509 Authentication', function () {
let client: MongoClient;
const validOptions: MongoClientOptions = {
tls: true,
tlsCertificateKeyFile: process.env.SSL_KEY_FILE,
tlsCAFile: process.env.SSL_CA_FILE,
authMechanism: 'MONGODB-X509' as const,
authSource: '$external'
};
this.afterEach(() => {
return client?.close();
});
context('When the user provides a valid certificate', function () {
before('create x509 user', createX509User);
after('drop x509 user', dropX509User);
it('successfully authenticates using x509', async function () {
client = new MongoClient(connectionString.toString(), validOptions);
const result = await client
.db('aws')
.collection('x509_test')
.estimatedDocumentCount()
.catch(error => error);
expect(result).to.not.be.instanceOf(MongoServerError);
expect(result).to.be.a('number');
});
context('when an incorrect username is supplied', function () {
it('fails to authenticate', async function () {
const uri = connectionString.clone();
uri.username = 'bob';
client = new MongoClient(uri.toString(), validOptions);
const error = await client.connect().catch(error => error);
expect(error).to.be.instanceOf(MongoServerError);
expect(error.codeName).to.match(/AuthenticationFailed/i);
});
});
});
context('when the client connects with an invalid certificate', function () {
// unlike other authentication mechanisms, x509 authentication 1) requires TLS and
// 2) the server uses the client certificate to derive a username to authenticate with
// against the $external database. This means that if a user attempts to connect to a
// cluster with an invalid certificate and tls is enabled, then the driver fails to connect and
// a server selection error is thrown.
it('throws a server selection error', async function () {
const invalidOptions: MongoClientOptions = {
// use an expired key file
tlsCertificateKeyFile: process.env.SSL_KEY_FILE_EXPIRED,
tlsCAFile: process.env.SSL_CA_FILE,
authMechanism: 'MONGODB-X509' as const,
authSource: '$external'
};
client = new MongoClient(connectionString.toString(), {
...invalidOptions,
serverSelectionTimeoutMS: 5000
});
const error = await client.connect().catch(e => e);
expect(error).to.be.instanceOf(MongoServerSelectionError);
});
});
context(
'when a valid cert is provided but the certificate does not correspond to a user',
function () {
it('fails to authenticate', async function () {
client = new MongoClient(connectionString.toString(), validOptions);
const error = await client.connect().catch(error => error);
expect(error).to.be.instanceOf(MongoServerError);
expect(error.codeName).to.match(/UserNotFound/i);
});
}
);
});
async function createX509User() {
const utilClient = new MongoClient(connectionString.toString(), {
tls: true,
tlsCertificateKeyFile: process.env.SSL_KEY_FILE,
tlsCAFile: process.env.SSL_CA_FILE,
serverSelectionTimeoutMS: 2000
});
try {
await utilClient.connect();
await utilClient.db('$external').command({
createUser: process.env.SUBJECT,
roles: [
{ role: 'readWrite', db: 'test' },
{ role: 'userAdminAnyDatabase', db: 'admin' }
]
});
} finally {
await utilClient.close();
}
}
async function dropX509User() {
const utilClient = new MongoClient(connectionString.toString(), {
tls: true,
tlsCertificateKeyFile: process.env.SSL_KEY_FILE,
tlsCAFile: process.env.SSL_CA_FILE,
serverSelectionTimeoutMS: 2000
});
try {
await utilClient.connect();
await utilClient.db('$external').command({
dropUser: process.env.SUBJECT
});
} finally {
await utilClient.close();
}
}