Skip to content

Commit 64addf2

Browse files
committed
JAVA-871, JAVA-976: Support for MONGODB-X509 authentication mechanism
1 parent 4e81118 commit 64addf2

6 files changed

Lines changed: 95 additions & 3 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import com.mongodb.BasicDBObject;
2+
import com.mongodb.DB;
3+
import com.mongodb.MongoClient;
4+
import com.mongodb.MongoClientOptions;
5+
import com.mongodb.MongoCredential;
6+
import com.mongodb.ServerAddress;
7+
8+
import javax.net.ssl.SSLSocketFactory;
9+
import java.net.UnknownHostException;
10+
import java.util.Arrays;
11+
12+
public class X509CredentialsExample {
13+
public static void main(String[] args) throws UnknownHostException {
14+
String server = args[0];
15+
String user = "CN=client,OU=kerneluser,O=10Gen,L=New York City,ST=New York,C=US";
16+
17+
System.out.println("server: " + server);
18+
System.out.println("user: " + user);
19+
20+
System.out.println();
21+
22+
MongoClient mongoClient = new MongoClient(new ServerAddress(server),
23+
Arrays.asList(MongoCredential.createMongoX509Credential(user)),
24+
new MongoClientOptions.Builder().socketFactory(SSLSocketFactory.getDefault()).build());
25+
DB testDB = mongoClient.getDB("test");
26+
27+
System.out.println("Count: " + testDB.getCollection("test").count());
28+
29+
System.out.println("Insert result: " + testDB.getCollection("test").insert(new BasicDBObject()));
30+
31+
}
32+
}

src/main/com/mongodb/DBPort.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ CommandResult authenticate(Mongo mongo, final MongoCredential credentials) {
319319
authenticator = new GSSAPIAuthenticator(mongo, credentials);
320320
} else if (credentials.getMechanism().equals(MongoCredential.PLAIN_MECHANISM)) {
321321
authenticator = new PlainAuthenticator(mongo, credentials);
322+
} else if (credentials.getMechanism().equals(MongoCredential.MONGODB_X509_MECHANISM)) {
323+
authenticator = new X509Authenticator(mongo, credentials);
322324
} else {
323325
throw new IllegalArgumentException("Unsupported authentication protocol: " + credentials.getMechanism());
324326
}
@@ -519,6 +521,30 @@ private CommandResult sendSaslContinue(final int conversationId, final byte[] ou
519521
public abstract String getMechanismName();
520522
}
521523

524+
class X509Authenticator extends Authenticator {
525+
X509Authenticator(final Mongo mongo, final MongoCredential credential) {
526+
super(mongo, credential);
527+
}
528+
529+
@Override
530+
CommandResult authenticate() {
531+
try {
532+
DB db = mongo.getDB(credential.getSource());
533+
CommandResult res = runCommand(db, getAuthCommand());
534+
res.throwOnError();
535+
return res;
536+
} catch (IOException e) {
537+
throw new MongoException.Network("IOException authenticating the connection", e);
538+
}
539+
}
540+
541+
private DBObject getAuthCommand() {
542+
return new BasicDBObject("authenticate", 1)
543+
.append("user", credential.getUserName())
544+
.append("mechanism", MongoCredential.MONGODB_X509_MECHANISM);
545+
}
546+
}
547+
522548
class NativeAuthenticator extends Authenticator {
523549
NativeAuthenticator(Mongo mongo, MongoCredential credentials) {
524550
super(mongo, credentials);

src/main/com/mongodb/MongoClientURI.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@
128128
* </ul>
129129
* <p>Authentication configuration:</p>
130130
* <ul>
131-
* <li>{@code authMechanism=MONGO-CR|GSSAPI|PLAIN}: The authentication mechanism to use if a credential was supplied.
132-
* The default is MONGODB-CR, which is the native MongoDB Challenge Response mechanism. For the GSSAPI mechanism, no password is accepted,
133-
* only the username.
131+
* <li>{@code authMechanism=MONGO-CR|GSSAPI|PLAIN|MONGODB-X509}: The authentication mechanism to use if a credential was supplied.
132+
* The default is MONGODB-CR, which is the native MongoDB Challenge Response mechanism. For the GSSAPI and MONGODB-X509 mechanisms,
133+
* no password is accepted, only the username.
134134
* </li>
135135
* <li>{@code authSource=string}: The source of the authentication credentials. This is typically the database that
136136
* the credentials have been created. The value defaults to the database specified in the path portion of the URI.
@@ -440,6 +440,9 @@ else if (mechanism.equals(MongoCredential.PLAIN_MECHANISM)) {
440440
else if (mechanism.equals(MongoCredential.MONGODB_CR_MECHANISM)) {
441441
return MongoCredential.createMongoCRCredential(userName, authSource, password);
442442
}
443+
else if (mechanism.equals(MongoCredential.MONGODB_X509_MECHANISM)) {
444+
return MongoCredential.createMongoX509Credential(userName);
445+
}
443446
else {
444447
throw new IllegalArgumentException("Unsupported authMechanism: " + mechanism);
445448
}

src/main/com/mongodb/MongoCredential.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public final class MongoCredential {
4848
*/
4949
public static final String MONGODB_CR_MECHANISM = "MONGODB-CR";
5050

51+
/**
52+
* The MongoDB X.509
53+
*/
54+
public static final String MONGODB_X509_MECHANISM = "MONGODB-X509";
5155

5256
private final String mechanism;
5357
private final String userName;
@@ -67,6 +71,16 @@ public static MongoCredential createMongoCRCredential(String userName, String da
6771
return new MongoCredential(MONGODB_CR_MECHANISM, userName, database, password);
6872
}
6973

74+
/**
75+
* Creates a MongoCredential instance for the MongoDB X.509 protocol.
76+
*
77+
* @param userName the user name
78+
* @return the credential
79+
*/
80+
public static MongoCredential createMongoX509Credential(String userName) {
81+
return new MongoCredential(MONGODB_X509_MECHANISM, userName, "$external", null);
82+
}
83+
7084
/**
7185
* Creates a MongoCredential instance for the PLAIN SASL mechanism.
7286
*

src/test/com/mongodb/MongoClientURITest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ public void testUserPass() {
107107
u = new MongoClientURI("mongodb://user:pass@host/?authMechanism=MONGODB-CR");
108108
assertEquals(MongoCredential.createMongoCRCredential(userName, "admin", password), u.getCredentials());
109109

110+
u = new MongoClientURI("mongodb://user@host/?authMechanism=MONGODB-X509");
111+
assertEquals(MongoCredential.createMongoX509Credential(userName), u.getCredentials());
112+
110113
u = new MongoClientURI("mongodb://bob:pwd@localhost/?authMechanism=PLAIN&authSource=db1");
111114
assertEquals(MongoCredential.createPlainCredential("bob", "db1", "pwd".toCharArray()), u.getCredentials());
112115

src/test/com/mongodb/MongoCredentialTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,18 @@ public void testPlainMechanism() {
143143
assertEquals("$external", credential.getSource());
144144
assertArrayEquals(password, credential.getPassword());
145145
}
146+
147+
@Test
148+
public void testX509Mechanism() {
149+
MongoCredential credential;
150+
151+
final String mechanism = MongoCredential.MONGODB_X509_MECHANISM;
152+
final String userName = "user";
153+
credential = MongoCredential.createMongoX509Credential(userName);
154+
155+
assertEquals(mechanism, credential.getMechanism());
156+
assertEquals(userName, credential.getUserName());
157+
assertEquals("$external", credential.getSource());
158+
assertArrayEquals(null, credential.getPassword());
159+
}
146160
}

0 commit comments

Comments
 (0)