Skip to content

Commit 32bc24a

Browse files
committed
JAVA-2771: Add prose integration test from auth spec
1 parent ab7f9da commit 32bc24a

File tree

2 files changed

+254
-0
lines changed

2 files changed

+254
-0
lines changed

driver-core/src/test/functional/com/mongodb/ClusterFixture.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import org.bson.codecs.DocumentCodec;
6666

6767
import java.util.ArrayList;
68+
import java.util.Collections;
6869
import java.util.HashMap;
6970
import java.util.List;
7071
import java.util.Map;
@@ -294,6 +295,23 @@ public static Cluster createCluster(final StreamFactory streamFactory) {
294295
return createCluster(getConnectionString(), streamFactory);
295296
}
296297

298+
299+
public static Cluster createCluster(final List<MongoCredential> credentials) {
300+
return createCluster(credentials, getStreamFactory());
301+
}
302+
303+
public static Cluster createAsyncCluster(final List<MongoCredential> credentials) {
304+
return createCluster(credentials, getAsyncStreamFactory());
305+
}
306+
307+
private static Cluster createCluster(final List<MongoCredential> credentials, final StreamFactory streamFactory) {
308+
return new DefaultClusterFactory().createCluster(ClusterSettings.builder().hosts(asList(getPrimary())).build(),
309+
ServerSettings.builder().build(),
310+
ConnectionPoolSettings.builder().maxSize(1).maxWaitQueueSize(1).build(),
311+
streamFactory, streamFactory, credentials, null, null, null,
312+
Collections.<MongoCompressor>emptyList());
313+
}
314+
297315
@SuppressWarnings("deprecation")
298316
private static Cluster createCluster(final ConnectionString connectionString, final StreamFactory streamFactory) {
299317
return new DefaultClusterFactory().createCluster(ClusterSettings.builder().applyConnectionString(connectionString).build(),
@@ -305,6 +323,10 @@ private static Cluster createCluster(final ConnectionString connectionString, fi
305323
connectionString.getCompressorList());
306324
}
307325

326+
public static StreamFactory getStreamFactory() {
327+
return new SocketStreamFactory(SocketSettings.builder().build(), getSslSettings());
328+
}
329+
308330
public static StreamFactory getAsyncStreamFactory() {
309331
String streamType = System.getProperty("org.mongodb.async.type", "nio2");
310332

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.internal.connection
18+
19+
import com.mongodb.ClusterFixture
20+
import com.mongodb.MongoCredential
21+
import com.mongodb.MongoSecurityException
22+
import com.mongodb.ReadConcern
23+
import com.mongodb.ReadPreference
24+
import com.mongodb.async.FutureResultCallback
25+
import com.mongodb.binding.AsyncClusterBinding
26+
import com.mongodb.binding.ClusterBinding
27+
import com.mongodb.operation.CommandReadOperation
28+
import com.mongodb.operation.CommandWriteOperation
29+
import com.mongodb.operation.DropUserOperation
30+
import org.bson.BsonDocumentWrapper
31+
import org.bson.Document
32+
import org.bson.codecs.DocumentCodec
33+
import spock.lang.IgnoreIf
34+
import spock.lang.Specification
35+
36+
import static com.mongodb.ClusterFixture.getBinding
37+
import static com.mongodb.ClusterFixture.createAsyncCluster
38+
import static com.mongodb.ClusterFixture.createCluster
39+
import static com.mongodb.ClusterFixture.isAuthenticated
40+
import static com.mongodb.MongoCredential.createCredential
41+
import static com.mongodb.MongoCredential.createScramSha1Credential
42+
import static com.mongodb.MongoCredential.createScramSha256Credential
43+
44+
@IgnoreIf({ !ClusterFixture.serverVersionAtLeast(4, 0) || !isAuthenticated() })
45+
class ScramSha256AuthenticationSpecification extends Specification {
46+
47+
static MongoCredential sha1Implicit = createCredential('sha1', 'admin', 'sha1'.toCharArray())
48+
static MongoCredential sha1Explicit = createScramSha1Credential('sha1', 'admin', 'sha1'.toCharArray())
49+
static MongoCredential sha256Implicit = createCredential('sha256', 'admin', 'sha256'.toCharArray())
50+
static MongoCredential sha256Explicit = createScramSha256Credential('sha256', 'admin', 'sha256'.toCharArray())
51+
static MongoCredential bothImplicit = createCredential('both', 'admin', 'both'.toCharArray())
52+
static MongoCredential bothExplicitSha1 = createScramSha1Credential('both', 'admin', 'both'.toCharArray())
53+
static MongoCredential bothExplicitSha256 = createScramSha256Credential('both', 'admin', 'both'.toCharArray())
54+
55+
static MongoCredential sha1AsSha256 = createScramSha256Credential('sha1', 'admin', 'sha1'.toCharArray())
56+
static MongoCredential sha256AsSha1 = createScramSha1Credential('sha256', 'admin', 'sha256'.toCharArray())
57+
static MongoCredential nonExistentUserImplicit = createCredential('nonexistent', 'admin', 'pwd'.toCharArray())
58+
59+
static MongoCredential userNinePrepped = createScramSha256Credential('IX', 'admin', 'IX'.toCharArray())
60+
static MongoCredential userNineUnprepped = createScramSha256Credential('IX', 'admin', 'I\u00ADX'.toCharArray())
61+
62+
static MongoCredential userFourPrepped = createScramSha256Credential('\u2168', 'admin', 'IV'.toCharArray())
63+
static MongoCredential userFourUnprepped = createScramSha256Credential('\u2168', 'admin', 'I\u00ADV'.toCharArray())
64+
65+
def setupSpec() {
66+
createUser('sha1', 'sha1', ['SCRAM-SHA-1'])
67+
createUser('sha256', 'sha256', ['SCRAM-SHA-256'])
68+
createUser('both', 'both', ['SCRAM-SHA-1', 'SCRAM-SHA-256'])
69+
createUser('IX', 'IX', ['SCRAM-SHA-256'])
70+
createUser('\u2168', '\u2163', ['SCRAM-SHA-256'])
71+
}
72+
73+
74+
def cleanupSpec() {
75+
dropUser('sha1')
76+
dropUser('sha256')
77+
dropUser('both')
78+
dropUser('IX')
79+
dropUser('\u2168')
80+
}
81+
82+
def createUser(final String userName, final String password, final List<String> mechanisms) {
83+
def createUserCommand = new Document('createUser', userName)
84+
.append('pwd', password)
85+
.append('roles', ['root'])
86+
.append('mechanisms', mechanisms)
87+
new CommandWriteOperation<Document>('admin',
88+
new BsonDocumentWrapper<Document>(createUserCommand, new DocumentCodec()), new DocumentCodec())
89+
.execute(getBinding())
90+
}
91+
92+
def dropUser(final String userName) {
93+
new DropUserOperation('admin', userName).execute(getBinding())
94+
}
95+
96+
def 'test authentication and authorization'() {
97+
given:
98+
def cluster = createCluster(credentials)
99+
100+
when:
101+
new CommandReadOperation<Document>('admin',
102+
new BsonDocumentWrapper<Document>(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
103+
.execute(new ClusterBinding(cluster, ReadPreference.primary(), ReadConcern.DEFAULT))
104+
105+
then:
106+
noExceptionThrown()
107+
108+
cleanup:
109+
cluster.close()
110+
111+
where:
112+
credentials << [[sha1Implicit],
113+
[sha1Explicit],
114+
[sha256Implicit],
115+
[sha256Explicit],
116+
[bothImplicit],
117+
[bothExplicitSha1],
118+
[bothExplicitSha256],
119+
[sha1Implicit, sha1Explicit, sha256Implicit, sha256Explicit, bothImplicit, bothExplicitSha1, bothExplicitSha256]
120+
]
121+
}
122+
123+
def 'test authentication and authorization async'() {
124+
given:
125+
def cluster = createAsyncCluster(credentials)
126+
def callback = new FutureResultCallback()
127+
128+
when:
129+
// make this synchronous
130+
new CommandReadOperation<Document>('admin',
131+
new BsonDocumentWrapper<Document>(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
132+
.executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary(), ReadConcern.DEFAULT), callback)
133+
callback.get()
134+
135+
then:
136+
noExceptionThrown()
137+
138+
cleanup:
139+
cluster.close()
140+
141+
where:
142+
credentials << [[sha1Implicit],
143+
[sha1Explicit],
144+
[sha256Implicit],
145+
[sha256Explicit],
146+
[bothImplicit],
147+
[bothExplicitSha1],
148+
[bothExplicitSha256],
149+
[sha1Implicit, sha1Explicit, sha256Implicit, sha256Explicit, bothImplicit, bothExplicitSha1, bothExplicitSha256]
150+
]
151+
}
152+
153+
def 'test authentication and authorization failure with wrong mechanism'() {
154+
given:
155+
def cluster = createCluster(credentials)
156+
157+
when:
158+
new CommandReadOperation<Document>('admin',
159+
new BsonDocumentWrapper<Document>(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
160+
.execute(new ClusterBinding(cluster, ReadPreference.primary(), ReadConcern.DEFAULT))
161+
162+
then:
163+
thrown(MongoSecurityException)
164+
165+
cleanup:
166+
cluster.close()
167+
168+
where:
169+
credentials << [[sha1AsSha256], [sha256AsSha1], [nonExistentUserImplicit]]
170+
}
171+
172+
def 'test authentication and authorization failure with wrong mechanism async'() {
173+
given:
174+
def cluster = createAsyncCluster(credentials)
175+
def callback = new FutureResultCallback()
176+
177+
when:
178+
new CommandReadOperation<Document>('admin',
179+
new BsonDocumentWrapper<Document>(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
180+
.executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary(), ReadConcern.DEFAULT), callback)
181+
callback.get()
182+
183+
then:
184+
thrown(MongoSecurityException)
185+
186+
cleanup:
187+
cluster.close()
188+
189+
where:
190+
credentials << [[sha1AsSha256], [sha256AsSha1], [nonExistentUserImplicit]]
191+
}
192+
193+
def 'test SASL Prep'() {
194+
given:
195+
def cluster = createCluster(credentials)
196+
197+
when:
198+
new CommandReadOperation<Document>('admin',
199+
new BsonDocumentWrapper<Document>(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
200+
.execute(new ClusterBinding(cluster, ReadPreference.primary(), ReadConcern.DEFAULT))
201+
202+
then:
203+
noExceptionThrown()
204+
205+
cleanup:
206+
cluster.close()
207+
208+
where:
209+
credentials << [[userNinePrepped], [userNineUnprepped], [userFourPrepped], [userFourUnprepped]]
210+
}
211+
212+
def 'test SASL Prep async'() {
213+
given:
214+
def cluster = createAsyncCluster(credentials)
215+
def callback = new FutureResultCallback()
216+
217+
when:
218+
new CommandReadOperation<Document>('admin',
219+
new BsonDocumentWrapper<Document>(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
220+
.executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary(), ReadConcern.DEFAULT), callback)
221+
callback.get()
222+
223+
then:
224+
noExceptionThrown()
225+
226+
cleanup:
227+
cluster.close()
228+
229+
where:
230+
credentials << [[userNinePrepped], [userNineUnprepped], [userFourPrepped], [userFourUnprepped]]
231+
}
232+
}

0 commit comments

Comments
 (0)