Skip to content

Commit a64f23d

Browse files
committed
try setting tls connection
1 parent d0f7f82 commit a64f23d

File tree

6 files changed

+156
-51
lines changed

6 files changed

+156
-51
lines changed

src/main/java/ru/cinimex/exporter/Config.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.apache.logging.log4j.LogManager;
44
import org.apache.logging.log4j.Logger;
55
import org.yaml.snakeyaml.Yaml;
6+
import ru.cinimex.exporter.mq.MQSecurityProperties;
67

78
import java.io.BufferedReader;
89
import java.io.File;
@@ -34,6 +35,7 @@ public class Config {
3435
private boolean sendPCFCommands;
3536
private boolean usePCFWildcards;
3637
private int scrapeInterval;
38+
private MQSecurityProperties mqSecurityProperties;
3739

3840
public Config(String path) {
3941
Yaml file = new Yaml();
@@ -65,6 +67,17 @@ public Config(String path) {
6567
this.sendPCFCommands = (boolean) pcfParameters.get("sendPCFCommands");
6668
this.usePCFWildcards = (boolean) pcfParameters.get("usePCFWildcards");
6769
this.scrapeInterval = (Integer) pcfParameters.get("scrapeInterval");
70+
boolean useTLS = (boolean) qmgrConnectionParams.get("useTLS");
71+
if (useTLS)
72+
mqSecurityProperties = new MQSecurityProperties(
73+
useTLS,
74+
(String) qmgrConnectionParams.get("keystorePath"),
75+
(String) qmgrConnectionParams.get("keystorePassword"),
76+
(String) qmgrConnectionParams.get("truststorePath"),
77+
(String) qmgrConnectionParams.get("truststorePassword"),
78+
(String) qmgrConnectionParams.get("sslProtocol"),
79+
(String) qmgrConnectionParams.get("cipherSuite")
80+
);
6881
logger.info("Successfully parsed configuration file!");
6982
}
7083

@@ -132,4 +145,7 @@ public List<String> getQueues() {
132145
return queues;
133146
}
134147

148+
public MQSecurityProperties getMqSecurityProperties() {
149+
return mqSecurityProperties;
150+
}
135151
}

src/main/java/ru/cinimex/exporter/ExporterLauncher.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static void main(String[] args) {
6363
}
6464

6565
MetricsManager.initMetrics(elements, monitoringTypes);
66-
MQSubscriberManager manager = new MQSubscriberManager(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
66+
MQSubscriberManager manager = new MQSubscriberManager(config);
6767
manager.runSubscribers(elements, objects, config.sendPCFCommands(), config.usePCFWildcards(),
6868
config.getScrapeInterval(), config.getConnTimeout());
6969
try {
@@ -87,7 +87,7 @@ private static ArrayList<PCFElement> getAllPublishedMetrics(Config config) {
8787
gmo.options = GMO;
8888
gmo.waitInterval = 30000;
8989
try {
90-
connection.establish(config.getQmgrHost(), config.getQmgrPort(), config.getQmgrChannel(), config.getQmgrName(), config.getUser(), config.getPassword(), config.useMqscp());
90+
connection.establish(config.getQmgrName(), MQConnection.createMQConnectionParams(config));
9191
topic = connection.createTopic(String.format(TOPIC_STRING, config.getQmgrName()));
9292
MQMessage msg = getEmptyMessage();
9393
topic.get(msg, gmo);
@@ -107,7 +107,8 @@ private static ArrayList<PCFElement> getAllPublishedMetrics(Config config) {
107107
elements.addAll(PCFDataParser.getPCFElements(pcfResponse));
108108
}
109109
}
110-
} catch (MQException | IOException e) {
110+
} catch (MQException |
111+
IOException e) {
111112
logger.error("Failed!", e);
112113
} finally {
113114
try {

src/main/java/ru/cinimex/exporter/mq/MQConnection.java

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,24 @@
77
import com.ibm.mq.constants.MQConstants;
88
import org.apache.logging.log4j.LogManager;
99
import org.apache.logging.log4j.Logger;
10+
import ru.cinimex.exporter.Config;
1011

12+
import javax.net.ssl.KeyManagerFactory;
13+
import javax.net.ssl.SSLContext;
14+
import javax.net.ssl.SSLSocketFactory;
15+
import javax.net.ssl.TrustManagerFactory;
16+
import java.io.FileInputStream;
17+
import java.io.IOException;
18+
import java.security.KeyManagementException;
19+
import java.security.KeyStore;
20+
import java.security.KeyStoreException;
21+
import java.security.NoSuchAlgorithmException;
22+
import java.security.UnrecoverableKeyException;
23+
import java.security.cert.CertificateException;
24+
import java.util.HashMap;
1125
import java.util.Hashtable;
26+
import java.util.Map;
27+
import java.util.Optional;
1228

1329
/**
1430
* Class represents MQ connection.
@@ -20,42 +36,55 @@ public class MQConnection {
2036
/**
2137
* Method creates connection properties Hashtable from connection parameters.
2238
*
23-
* @param host - host, where queue manager is located.
24-
* @param port - queue manager's port.
25-
* @param channel - queue manager's channel.
26-
* @param user - user, which has enough privilege on the queue manager (optional).
27-
* @param password - password, which is required to establish connection with queue manager (optional).
28-
* @param useMQCSP - flag, which indicates, if MQCSP auth should be used.
39+
* @param config - config.
2940
* @return - returns prepared structure with all parameters transformed into queue manager's format.
3041
*/
31-
protected static Hashtable<String, Object> createMQConnectionParams(String host, int port, String channel, String user, String password, boolean useMQCSP) {
32-
Hashtable<String, Object> properties = new Hashtable<>();
33-
properties.put(MQConstants.TRANSPORT_PROPERTY, host == null ? MQConstants.TRANSPORT_MQSERIES_BINDINGS : MQConstants.TRANSPORT_MQSERIES_CLIENT);
34-
if (host != null) properties.put(MQConstants.HOST_NAME_PROPERTY, host);
35-
if (port != 0) properties.put(MQConstants.PORT_PROPERTY, port);
36-
if (channel != null) properties.put(MQConstants.CHANNEL_PROPERTY, channel);
37-
if (user != null || password != null) {
38-
if (useMQCSP) properties.put(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
39-
if (user != null) properties.put(MQConstants.USER_ID_PROPERTY, user);
40-
if (password != null) properties.put(MQConstants.PASSWORD_PROPERTY, password);
42+
public static Map<String, Object> createMQConnectionParams(Config config) {
43+
Map<String, Object> properties = new HashMap<>();
44+
properties.put(MQConstants.TRANSPORT_PROPERTY, config.getQmgrHost() == null ? MQConstants.TRANSPORT_MQSERIES_BINDINGS : MQConstants.TRANSPORT_MQSERIES_CLIENT);
45+
if (config.getQmgrHost() != null) properties.put(MQConstants.HOST_NAME_PROPERTY, config.getQmgrHost());
46+
if (config.getQmgrPort() != 0) properties.put(MQConstants.PORT_PROPERTY, config.getQmgrPort());
47+
if (config.getQmgrChannel() != null) properties.put(MQConstants.CHANNEL_PROPERTY, config.getQmgrChannel());
48+
if (config.getUser() != null || config.getPassword() != null) {
49+
if (config.useMqscp()) properties.put(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
50+
if (config.getUser() != null) properties.put(MQConstants.USER_ID_PROPERTY, config.getUser());
51+
if (config.getPassword() != null) properties.put(MQConstants.PASSWORD_PROPERTY, config.getPassword());
52+
}
53+
MQSecurityProperties mqSecurityProperties = config.getMqSecurityProperties();
54+
if (mqSecurityProperties != null && mqSecurityProperties.isUseTLS()) {
55+
KeyStore keyStore = getStore(mqSecurityProperties.getKeystorePath(), mqSecurityProperties.getKeystorePassword());
56+
KeyStore trustStore = getStore(mqSecurityProperties.getTruststorePath(), mqSecurityProperties.getTruststorePassword());
57+
58+
SSLContext sslContext = null;
59+
try {
60+
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
61+
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
62+
trustManagerFactory.init(trustStore);
63+
keyManagerFactory.init(keyStore, mqSecurityProperties.getKeystorePassword().toCharArray());
64+
sslContext = SSLContext.getInstance(mqSecurityProperties.getSslProtocol());
65+
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
66+
} catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyManagementException e1) {
67+
logger.error("Failed!", e1);
68+
}
69+
70+
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
71+
72+
properties.put(MQConstants.SSL_CIPHER_SUITE_PROPERTY, mqSecurityProperties.getCipherSuite());
73+
properties.put(MQConstants.SSL_SOCKET_FACTORY_PROPERTY, sslSocketFactory);
74+
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");
4175
}
4276
return properties;
4377
}
4478

45-
/**
46-
* Method establishes connection with queue manager.
47-
*
48-
* @param host - host, where queue manager is located.
49-
* @param port - queue manager's port.
50-
* @param channel - queue manager's channel.
51-
* @param qmName - queue manager's name.
52-
* @param user - user, which has enough privilege on the queue manager (optional).
53-
* @param password - password, which is required to establish connection with queue manager (optional).
54-
* @param useMQCSP - flag, which indicates, if MQCSP auth should be used.
55-
*/
56-
public void establish(String host, int port, String channel, String qmName, String user, String password, boolean useMQCSP) throws MQException {
57-
Hashtable<String, Object> connectionProperties = createMQConnectionParams(host, port, channel, user, password, useMQCSP);
58-
queueManager = new MQQueueManager(qmName, connectionProperties);
79+
private static KeyStore getStore(String storePath, String storePassword) {
80+
KeyStore keyStore = null;
81+
try (FileInputStream keyStoreInput = new FileInputStream(storePath)) {
82+
keyStore = KeyStore.getInstance("JKS");
83+
keyStore.load(keyStoreInput, storePassword.toCharArray());
84+
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
85+
logger.error("Failed to get key or trust store: ", e);
86+
}
87+
return keyStore;
5988
}
6089

6190
/**
@@ -64,8 +93,8 @@ public void establish(String host, int port, String channel, String qmName, Stri
6493
* @param qmNqme - queue manager's name.
6594
* @param connectionProperties - prepared structure with all parameters transformed into queue manager's format. See {@link #createMQConnectionParams(String, int, String, String, String, boolean)} for more info.
6695
*/
67-
public void establish(String qmNqme, Hashtable<String, Object> connectionProperties) throws MQException {
68-
queueManager = new MQQueueManager(qmNqme, connectionProperties);
96+
public void establish(String qmNqme, Map<String, Object> connectionProperties) throws MQException {
97+
queueManager = new MQQueueManager(qmNqme, new Hashtable<>(connectionProperties));
6998
}
7099

71100
/**
@@ -100,4 +129,5 @@ public MQTopic createTopic(String topic) throws MQException {
100129
public MQQueueManager getQueueManager() {
101130
return this.queueManager;
102131
}
132+
103133
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package ru.cinimex.exporter.mq;
2+
3+
public class MQSecurityProperties {
4+
private boolean useTLS;
5+
private String keystorePath;
6+
private String keystorePassword;
7+
private String truststorePath;
8+
private String truststorePassword;
9+
private String sslProtocol;
10+
private String cipherSuite;
11+
12+
public MQSecurityProperties(boolean useTLS, String keystorePath, String keystorePassword, String truststorePath, String truststorePassword, String sslProtocol, String cipherSuite) {
13+
this.useTLS = useTLS;
14+
this.keystorePath = keystorePath;
15+
this.keystorePassword = keystorePassword;
16+
this.truststorePath = truststorePath;
17+
this.truststorePassword = truststorePassword;
18+
this.sslProtocol = sslProtocol;
19+
this.cipherSuite = cipherSuite;
20+
}
21+
22+
public String getKeystorePath() {
23+
return keystorePath;
24+
}
25+
26+
public String getKeystorePassword() {
27+
return keystorePassword;
28+
}
29+
30+
public String getTruststorePath() {
31+
return truststorePath;
32+
}
33+
34+
public String getTruststorePassword() {
35+
return truststorePassword;
36+
}
37+
38+
public String getSslProtocol() {
39+
return sslProtocol;
40+
}
41+
42+
public String getCipherSuite() {
43+
return cipherSuite;
44+
}
45+
46+
public boolean isUseTLS() {
47+
return useTLS;
48+
}
49+
}

src/main/java/ru/cinimex/exporter/mq/MQSubscriberManager.java

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.ibm.mq.MQException;
44
import org.apache.logging.log4j.LogManager;
55
import org.apache.logging.log4j.Logger;
6+
import ru.cinimex.exporter.Config;
67
import ru.cinimex.exporter.mq.pcf.PCFElement;
78

89
import java.util.*;
@@ -15,25 +16,19 @@
1516
*/
1617
public class MQSubscriberManager {
1718
private static final Logger logger = LogManager.getLogger(MQSubscriberManager.class);
18-
private Hashtable<String, Object> connectionProperties;
19+
private Map<String, Object> connectionProperties;
1920
private String queueManagerName;
2021
private ArrayList<MQSubscriber> subscribers;
2122
private ScheduledExecutorService executor;
2223

2324
/**
2425
* Constructor sets params for connecting to target queue manager.
2526
*
26-
* @param host - host, where queue manager is located.
27-
* @param port - queue manager's port.
28-
* @param channel - queue manager's channel.
29-
* @param qmName - queue manager's name.
30-
* @param user - user, which has enough privilege on the queue manager (optional).
31-
* @param password - password, which is required to establish connection with queue manager (optional).
32-
* @param useMQCSP - flag, which indicates, if MQCSP auth should be used.
27+
* @param config - config.
3328
*/
34-
public MQSubscriberManager(String host, int port, String channel, String qmName, String user, String password, boolean useMQCSP) {
35-
connectionProperties = MQConnection.createMQConnectionParams(host, port, channel, user, password, useMQCSP);
36-
queueManagerName = qmName;
29+
public MQSubscriberManager(Config config) {
30+
connectionProperties = MQConnection.createMQConnectionParams(config);
31+
queueManagerName = config.getQmgrName();
3732
}
3833

3934
/**
@@ -64,7 +59,7 @@ public void runSubscribers(List<PCFElement> elements, List<MQObject> objects, bo
6459
if (!subscribers.isEmpty()) {
6560
logger.info("Successfully launched {} subscribers!", subscribers.size());
6661
} else {
67-
logger.warn("Didn't launch any subscriber. Exporter finishes it's work!", subscribers.size());
62+
logger.warn("Didn't launch any subscriber. Exporter finishes it's work!");
6863
System.exit(1);
6964
}
7065

@@ -110,7 +105,7 @@ private void addTopicSubscriber(MQObject object, PCFElement element, int timeout
110105
PCFElement objElement = new PCFElement(element.getTopicString(), element.getRows());
111106
objElement.formatTopicString(object.getName());
112107
try {
113-
subscribers.add(new MQTopicSubscriber(objElement, queueManagerName, connectionProperties, timeout, queueManagerName, object.getName()));
108+
subscribers.add(new MQTopicSubscriber(objElement, queueManagerName, new Hashtable<>(connectionProperties), timeout, queueManagerName, object.getName()));
114109
} catch (MQException e) {
115110
logger.error("Error during creating topic subscriber: ", e);
116111
}
@@ -125,7 +120,7 @@ private void addTopicSubscriber(MQObject object, PCFElement element, int timeout
125120
*/
126121
private void addTopicSubscriber(PCFElement element, int timeout) {
127122
try {
128-
subscribers.add(new MQTopicSubscriber(element, queueManagerName, connectionProperties, timeout, queueManagerName));
123+
subscribers.add(new MQTopicSubscriber(element, queueManagerName, new Hashtable<>(connectionProperties), timeout, queueManagerName));
129124
} catch (MQException e) {
130125
logger.error("Error during creating topic subscriber: ", e);
131126
}
@@ -142,7 +137,7 @@ private void addPCFSubscribers(Map<MQObject.MQType, ArrayList<MQObject>> objects
142137
executor = Executors.newScheduledThreadPool(corePoolSize);
143138
for (Map.Entry<MQObject.MQType, ArrayList<MQObject>> entry : objects.entrySet()) {
144139
if (!entry.getValue().isEmpty()) {
145-
MQPCFSubscriber subscriber = new MQPCFSubscriber(queueManagerName, connectionProperties, entry.getValue());
140+
MQPCFSubscriber subscriber = new MQPCFSubscriber(queueManagerName, new Hashtable<>(connectionProperties), entry.getValue());
146141
subscribers.add(subscriber);
147142
logger.debug("Starting subscriber for sending direct PCF commands to retrieve statistics about object with type {} and name {}.", entry.getKey().name());
148143
executor.scheduleAtFixedRate(subscriber, 0, interval, TimeUnit.SECONDS);
@@ -161,7 +156,7 @@ private void addPCFSubscribers(List<MQObject> objects, int interval) {
161156
int corePoolSize = objects.size();
162157
ScheduledExecutorService executor = Executors.newScheduledThreadPool(corePoolSize);
163158
for (MQObject object : objects) {
164-
MQPCFSubscriber subscriber = new MQPCFSubscriber(queueManagerName, connectionProperties, object);
159+
MQPCFSubscriber subscriber = new MQPCFSubscriber(queueManagerName, new Hashtable<>(connectionProperties), object);
165160
subscribers.add(subscriber);
166161
logger.debug("Starting subscriber for sending direct PCF commands to retrieve statistics about object with type {} and name {}.", object.getType().name(), object.getName());
167162
executor.scheduleAtFixedRate(subscriber, 0, interval, TimeUnit.SECONDS);

src/main/resources/exporter_config.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ qmgrConnectionParams:
1919
# How long to wait until metrics are published by queue manager (milliseconds).
2020
# Value must be at least 10000 (periodicity with which metrics are published by MQ).
2121
connTimeout: 12000
22+
#
23+
useTLS: true
24+
#
25+
keystorePath: /path
26+
#
27+
keystorePassword: qweqwe
28+
#
29+
truststorePath: /path
30+
#
31+
truststorePassword: qweqwe
32+
#
33+
sslProtocol: TLSv1.2
34+
# or SSL_RSA_WITH_AES_256_CBC_SHA256?
35+
cipherSuite: TLS_RSA_WITH_AES_256_CBC_SHA256
2236

2337
# Prometheus connection information -------------------------------
2438
prometheusEndpointParams:

0 commit comments

Comments
 (0)