Skip to content

Commit f0ce2fa

Browse files
authored
Add support for connecting to MongoDB using SSL (#188)
* Add support for connecting to MongoDB using SSL
1 parent 673043d commit f0ce2fa

5 files changed

Lines changed: 76 additions & 17 deletions

File tree

doc/INSTALL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ authorization for applications on Liberty, see [Configuring authorization for ap
5252

5353
### MongoDB configuration
5454

55-
If your MongoDB instance uses authentication or if other parameters, such as the MongoDB port,
56-
are non-default then you may need to customize the properties in `bootstrap.properties`.
55+
If your MongoDB instance uses authentication or SSL, or if other parameters such as the MongoDB port
56+
are non-default then you will need to customize the properties in `bootstrap.properties`.
5757

5858
## Starting the server
5959

server/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ def requiredSpecJars = [
5151
'com.ibm.*.javaee.annotation.1.1_*.jar']
5252

5353
def requiredIbmJars = [
54-
'com.ibm.*.passwordUtil_*.jar']
54+
'com.ibm.*.passwordUtil_*.jar',
55+
'com.ibm.*.ssl_*.jar']
5556

5657
def requiredThirdPartyJars = [
5758
'com.ibm.websphere.appserver.thirdparty.jaxrs_*.jar']

server/config/bootstrap.properties

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
1-
# For a single mongodb server:
1+
#### Basic configuration ####
2+
# For a single MongoDB server:
23
#lars.mongo.hostname=localhost
34
#lars.mongo.port=27017
45

5-
# For a mongodb cluster:
6+
# Or for a MongoDB cluster add as many hostname/port pairs as needed:
67
#lars.mongo.hostname0=
78
#lars.mongo.port0=
89
#lars.mongo.hostname1=
910
#lars.mongo.port1=
1011

12+
# Name of the database (will be created if needed)
1113
lars.mongo.dbname=larsDB
1214

15+
# Use slightly safer write concern than the default
16+
lars.mongo.writeConcern=JOURNALED
17+
18+
#### Authentication ####
1319
# If authentication is required:
1420
#lars.mongo.user=
1521
#lars.mongo.pass.encoded=
22+
# If a different db is used for authentication:
23+
#lars.mongo.authdb=admin
1624

17-
# Use slightly safer write concern than the default
18-
lars.mongo.writeConcern=JOURNALED
25+
#### SSL Configuration ####
26+
# To connect to MongoDB using SSL (or TLS)
27+
#lars.mongo.sslEnabled=true
28+
# Use this to specify custom SSL settings, for example if a trust store
29+
# is required. The value of this property refers to an <ssl> entry in
30+
# the server.xml
31+
#lars.mongo.sslConfig=mongoSSLConfig

server/config/server.xml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,17 @@ limitations under the License.
4949
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
5050
<httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
5151

52-
<!-- This library must be used by the WAR app in order for both the app and the MongoDB feature to see the
53-
same MongoDB driver classes.
54-
-->
52+
<!-- This library must be used by the WAR app in order to see the MongoDB driver classes. -->
5553
<library id="mongo-lib" apiTypeVisibility="spec,ibm-api,api,third-party">
5654
<fileset dir="${shared.resource.dir}/libs" includes="mongo-java-driver*.jar" />
5755
</library>
5856

57+
<!-- Uncomment this to specify a custom trust store if SSL is required for connecting to MongoDB -->
58+
<!--
59+
<ssl id="mongoSSLConfig" trustStoreRef="mongoTrustStore" keyStoreRef="mongoTrustStore" />
60+
<keyStore id="mongoTrustStore" password="somePassword location="mongoStore.p12" type="PKCS12" />
61+
-->
62+
5963
<!-- Uncomment this to override the base URL (may be useful if lars is behind a reverse proxy -->
6064
<!-- <jndiEntry id="lars/URLBase" jndiName="lars/URLBase" value="http://my.external.domain/repo/" /> -->
6165

@@ -76,4 +80,5 @@ limitations under the License.
7680
</application-bnd>
7781
-->
7882
</webApplication>
83+
7984
</server>

server/src/main/java/com/ibm/ws/lars/rest/mongo/MongoProducer.java

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import javax.enterprise.inject.Produces;
1616
import javax.annotation.PostConstruct;
1717
import javax.inject.Inject;
18+
import javax.net.ssl.SSLContext;
1819

1920
import com.ibm.websphere.crypto.PasswordUtil;
2021
import com.mongodb.MongoClient;
@@ -39,9 +40,12 @@ public class MongoProducer {
3940
private static final Logger logger = Logger.getLogger(MongoProducer.class.getCanonicalName());
4041

4142
private String dbName = null;
43+
private String authDbName = null;
4244
private String user = null;
4345
private String encodedPass = null;
4446
private String requestedWriteConcern = null;
47+
private boolean sslEnabled = false;
48+
private String sslConfig = null;
4549
private ArrayList<ServerAddress> servers = new ArrayList<ServerAddress>(2);
4650

4751
@PostConstruct
@@ -54,10 +58,22 @@ private void readConfig() {
5458
// user and password (optional - if not set, use unauthenticated access)
5559
user = sysprops.getProperty("lars.mongo.user");
5660
encodedPass = sysprops.getProperty("lars.mongo.pass.encoded");
61+
authDbName = sysprops.getProperty("lars.mongo.authdb");
62+
if(authDbName == null) {
63+
authDbName = dbName;
64+
}
5765

5866
// writeConcern (optional - if not set use the default "ACKNOWLEDGED")
5967
requestedWriteConcern = sysprops.getProperty("lars.mongo.writeConcern");
6068

69+
// sslEnabled (optional - if not set, assume false)
70+
if("true".equalsIgnoreCase(sysprops.getProperty("lars.mongo.sslEnabled","false"))) {
71+
sslEnabled = true;
72+
}
73+
74+
// sslConfig (optional, only used if ssl is enabled)
75+
sslConfig = sysprops.getProperty("lars.mongo.sslConfig");
76+
6177
// look for all lars.mongo.hostname* properties, in alphabetical order
6278
Enumeration keysEnum = sysprops.keys();
6379
Vector<String> keyList = new Vector<String>();
@@ -89,7 +105,9 @@ private void readConfig() {
89105

90106
@Produces
91107
public MongoClient createMongo() {
92-
MongoClientOptions opts;
108+
MongoClientOptions.Builder builder = MongoClientOptions.builder();
109+
110+
// set the WriteConcern, if specified
93111
if(requestedWriteConcern != null) {
94112
WriteConcern wc;
95113
switch(requestedWriteConcern)
@@ -131,26 +149,48 @@ public MongoClient createMongo() {
131149
wc = WriteConcern.ACKNOWLEDGED;
132150
logger.warning("No WriteConcern named " + requestedWriteConcern + " found. Using default WriteConcern of ACKNOWLEDGED.");
133151
}
134-
opts = new MongoClientOptions.Builder().writeConcern(wc).build();
152+
builder = builder.writeConcern(wc);
135153
logger.info("createMongo: using write concern " + requestedWriteConcern);
136154
} else {
137-
opts = new MongoClientOptions.Builder().build();
138155
logger.info("createMongo: using default write concern");
139156
}
140157

141-
if(encodedPass == null) {
142-
logger.info("createMongo: connecting to database "+dbName+" using unauthenticated access");
158+
// Configure SSL
159+
if(sslEnabled) {
160+
try {
161+
SSLContext sslContext;
162+
if(sslConfig == null) {
163+
sslContext = SSLContext.getDefault();
164+
} else {
165+
sslContext = com.ibm.websphere.ssl.JSSEHelper.getInstance().getSSLContext(sslConfig, Collections.emptyMap(), null);
166+
}
167+
logger.info("createMongo: SSL enabled");
168+
builder = builder.sslEnabled(sslEnabled).sslContext(sslContext);
169+
} catch(com.ibm.websphere.ssl.SSLException ex) {
170+
logger.severe("createMongo: Failed to initialize SSL: "+ex.getMessage());
171+
return null;
172+
} catch(java.security.NoSuchAlgorithmException ex) {
173+
logger.severe("createMongo: Failed to initialize SSL: "+ex.getMessage());
174+
return null;
175+
}
176+
}
177+
MongoClientOptions opts = builder.build();
178+
179+
// Configure credentials, and connect
180+
if(encodedPass == null) {
181+
logger.info("createMongo: connecting using unauthenticated access");
143182
return new MongoClient(servers, opts);
144183
} else {
145184
String password = PasswordUtil.passwordDecode(encodedPass);
146-
MongoCredential creds = MongoCredential.createCredential(user, dbName, password.toCharArray());
147-
logger.info("createMongo: connecting to database "+dbName+" as user "+user);
185+
MongoCredential creds = MongoCredential.createCredential(user, authDbName, password.toCharArray());
186+
logger.info("createMongo: connecting using user "+user+" and authentication database "+authDbName);
148187
return new MongoClient(servers, creds, opts);
149188
}
150189
}
151190

152191
@Produces
153192
public DB createDB(MongoClient client) {
193+
logger.info("createMongo: connecting to database "+dbName);
154194
return client.getDB(dbName);
155195
}
156196

0 commit comments

Comments
 (0)