Skip to content

Commit 7ab349d

Browse files
authored
Merge pull request #39 from IBMStreams/develop
Develop
2 parents 6cd3725 + 7a2e860 commit 7ab349d

File tree

19 files changed

+144
-34
lines changed

19 files changed

+144
-34
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,8 @@
3636
* Enhancement in operator HTTPTupleInjection: insert the default values
3737
* Correction in operator HTTPTupleView: selection of partition fails if attribute has type boolean
3838

39+
## v4.2.0
40+
* Fixed: Operators can not load trustStore file if path is not an absolute one
41+
* Enhancemement: Parameter contextResourceBase is now independent from parameter context
42+
* Enhancemement in description for generation of client certitficate which can be used in a brower
43+

com.ibm.streamsx.inetserver/com.ibm.streamsx.inet.rest/namespace-info.spl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,13 @@
3636
* [http://d3js.org|D3].
3737
*
3838
* Meta-data for the streams connected to the operators is also available through `HTTP GET` requests,
39-
* to allow JavaScript applications to self-discover the format of the data.
39+
* to allow JavaScript applications to self-discover the format of the data and the to self-discover the connected
40+
* streams and exposed contexts:
41+
* * `ports/info` Meta information of the connected ports
42+
* * `contexts/info` Meta information of the exposed contexts
43+
* * `/` default context mapped to `application_directory/opt/html`
4044
*
41-
* These fixed contexts are provided by the operators:
45+
* More fixed contexts are provided by the operators:
4246
* * `streamsx.inet.resources` Utilities provided by the operators.
4347
* * `streamsx.inet.dojo` The Dojo Javascript library located at `$STREAMS_INSTALL/ext/dojo`.
4448
*

com.ibm.streamsx.inetserver/com.ibm.streamsx.inet/namespace-info.spl

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,28 +76,40 @@
7676
* * `trustStorePassword` - Password to the trust store.
7777
*
7878
* # Server Key and Certificate
79-
* To generate a server key pair use the following command:
79+
* To generate a server key pair in a jks-keystore. Use the following command:
8080
* keytool -genkeypair -keyalg RSA -alias mykey -keypass changeit -storepass changeit -validity 1000 -keystore etc/keystore.jks -dname "CN=<name/hostname>, OU=<org unit>, O=<organization>, L=<locality>, ST=<state>, C=<two-letter country code>"
8181
*
8282
* Check the content of an keystore file:
8383
* keytool -list -v -keystore etc/keystore.jks
8484
*
85-
* Extract the certificate for the client trust manager:
85+
* Extract the certificate for the client trust manager (pem-file):
8686
* keytool -export -rfc -alias mykey -file etc/servercert.pem -storepass changeit -keystore etc/keystore.jks
8787
*
88-
* Insert the the certificate into a new truststore at the client site:
89-
* keytool -import -file etc/servercert.pem -alias mykey -keystore etc/cacert.jks -storepass changeit -trustcacerts'
88+
* Insert the certificate into a new jks-truststore at the client site:
89+
* keytool -import -file etc/servercert.pem -alias mykey -keystore etc/cacert.jks -storepass changeit -trustcacerts
9090
*
91-
* # Client Key and Certificate
91+
* # Client Key and Certificate for clients with jks based keystore
9292
*
93-
* The `dname` of an client key must match to the `dname` of the server key. To generate a client key use the following commands:
94-
* keytool -genkeypair -keyalg RSA -alias myclientkey -keypass changeit -storepass changeit -keystore etc/clientkey.jks -dname '<the dname string from the server certificate>'
93+
* To generate a client key use the following commands:
94+
* keytool -genkeypair -keyalg RSA -alias myclientkey -keypass changeit -storepass changeit -keystore etc/clientkey.jks -dname "CN=<name/hostname>, OU=<org unit>, O=<organization>, L=<locality>, ST=<state>, C=<two-letter country code>"
9595
*
9696
* Extract the certificate for the server trust manager:
9797
* keytool -export -rfc -alias myclientkey -file etc/clientkey.pem -keystore etc/clientkey.jks -storepass changeit -keypass changeit
9898
*
99-
* Insert the the certificate into a new truststore at the srver site:
99+
* Insert the the certificate into a new jks-truststore at the server site:
100100
* keytool -import -file etc/clientkey.pem -alias myclientkey -keystore etc/cacert.jks -storepass changeit -trustcacerts
101+
*
102+
* # Client Key and Certificate for a Browser / Clients with PKCS:
103+
* Generate a client key pair in a .pfx file that can be imported into browser.
104+
* keytool -genkeypair -keyalg RSA -alias myclientkey -storepass changeit -keystore etc/client.pfx -storetype PKCS12 -dname "CN=<name/hostname>, OU=<org unit>, O=<organization>, L=<locality>, ST=<state>, C=<two-letter country code>"
105+
*
106+
* Export for server as .pem file:
107+
* keytool -export -rfc -alias myclientkey -file etc/clientkey.pem -storepass changeit -keystore etc/client.pfx -storetype PKCS12
108+
*
109+
* Import the certificate into a new jks-truststore at the server site:
110+
* keytool -import -file etc/clientkey.pem -keystore etc/cacerts.jks -storepass changeit -trustcacerts
111+
* rm etc/clientkey.pem
112+
*
101113
*/
102114

103115
namespace com.ibm.streamsx.inet;

com.ibm.streamsx.inetserver/impl/java/src/com/ibm/streamsx/inet/rest/engine/ServletEngine.java

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@
4747
import org.eclipse.jetty.servlet.ServletHolder;
4848
import org.eclipse.jetty.util.ssl.SslContextFactory;
4949
import org.eclipse.jetty.util.thread.ThreadPool;
50-
import org.eclipse.jetty.webapp.WebAppContext;
5150

5251
import com.ibm.streams.operator.OperatorContext;
5352
import com.ibm.streams.operator.StreamingData;
5453
import com.ibm.streams.operator.management.OperatorManagement;
5554
import com.ibm.streamsx.inet.rest.ops.Functions;
5655
import com.ibm.streamsx.inet.rest.ops.PostTuple;
5756
import com.ibm.streamsx.inet.rest.ops.ServletOperator;
57+
import com.ibm.streamsx.inet.rest.servlets.ExposedContextInfo;
5858
import com.ibm.streamsx.inet.rest.servlets.ExposedPortsInfo;
5959
import com.ibm.streamsx.inet.rest.servlets.PortInfo;
6060
import com.ibm.streamsx.inet.rest.setup.ExposedPort;
@@ -178,6 +178,10 @@ public void join() throws InterruptedException {
178178
portsIntro.addServlet(new ServletHolder( new ExposedPortsInfo(exposedPorts)), "/info");
179179
addHandler(portsIntro);
180180

181+
ServletContextHandler contextIntro = new ServletContextHandler(server, "/contexts", ServletContextHandler.SESSIONS);
182+
contextIntro.addServlet(new ServletHolder( new ExposedContextInfo(staticContexts)), "/info");
183+
addHandler(contextIntro);
184+
181185
// making a abs path by combining toolkit directory with the opt/resources dir
182186
URI baseToolkitDir = operatorContext.getToolkitDirectory().toURI();
183187
addStaticContext("streamsx.inet.resources", PathConversionHelper.convertToAbsPath(baseToolkitDir, "opt/resources"));
@@ -212,14 +216,18 @@ private void setHTTPSConnector(OperatorContext operatorContext, Server server, i
212216
File keyStorePathFile = new File(keyStorePath);
213217
if (!keyStorePathFile.isAbsolute())
214218
keyStorePathFile = new File(operatorContext.getPE().getApplicationDirectory(), keyStorePath);
215-
sslContextFactory.setKeyStorePath(keyStorePathFile.getAbsolutePath());
219+
String keyStorePathToLoad = keyStorePathFile.getAbsolutePath();
220+
System.out.println("keyStorePathToLoad=" + keyStorePathToLoad);
221+
sslContextFactory.setKeyStorePath(keyStorePathToLoad);
216222
//the key store password is optional
217223
if (operatorContext.getParameterNames().contains(SSL_KEYSTORE_PASSWORD_PARAM)) {
218224
String keyStorePassword = operatorContext.getParameterValues(SSL_KEYSTORE_PASSWORD_PARAM).get(0);
225+
System.out.println("keyStorePassword=****");
219226
sslContextFactory.setKeyStorePassword(Functions.obfuscate(keyStorePassword));
220227
}
221228
//Key password is required
222229
String keyPassword = operatorContext.getParameterValues(SSL_KEY_PASSWORD_PARAM).get(0);
230+
System.out.println("keyPassword=****");
223231
sslContextFactory.setKeyManagerPassword(Functions.obfuscate(keyPassword));
224232
//Key alias
225233
String alias = operatorContext.getParameterValues(SSL_CERT_ALIAS_PARAM).get(0);
@@ -230,10 +238,13 @@ private void setHTTPSConnector(OperatorContext operatorContext, Server server, i
230238
File trustStorePathFile = new File(trustStorePath);
231239
if (!trustStorePathFile.isAbsolute())
232240
trustStorePathFile = new File(operatorContext.getPE().getApplicationDirectory(), trustStorePath);
233-
sslContextFactory.setTrustStorePath(trustStorePath);
241+
String trustStorePathToLoad = trustStorePathFile.getAbsolutePath();
242+
System.out.println("trustStorePathToLoad=" + trustStorePathToLoad);
243+
sslContextFactory.setTrustStorePath(trustStorePathToLoad);
234244
sslContextFactory.setNeedClientAuth(true);
235245
if (operatorContext.getParameterNames().contains(SSL_TRUSTSTORE_PASSWORD_PARAM)) {
236246
String trustStorePassword = operatorContext.getParameterValues(SSL_TRUSTSTORE_PASSWORD_PARAM).get(0);
247+
System.out.println("trustStorePassword=****");
237248
sslContextFactory.setTrustStorePassword(Functions.obfuscate(trustStorePassword));
238249
}
239250
}
@@ -421,12 +432,21 @@ public void registerOperator(ServletOperator operator, Object conduit) throws Ex
421432
staticContext.setAttribute("operator.conduit", conduit);
422433
}
423434

424-
// For a static context just use the name of the
425-
// base operator (without the composite nesting qualifiers)
426-
// as the lead in for resources exposed by this operator.
427-
// Otherwise use the full name of the operator so that it is unique.
435+
// If there is a context parameter in this operator
436+
// just use the base name of the operator (without the composite nesting qualifiers)
437+
// as the lead in for port resources exposed by this operator.
438+
// Otherwise use the full operator name so that it is unique.
439+
String ctxName = null;
440+
if (operatorContext.getParameterNames().contains(CONTEXT_PARAM)) {
441+
ctxName = operatorContext.getParameterValues(CONTEXT_PARAM).get(0);
442+
443+
if ("".equals(ctxName))
444+
throw new IllegalArgumentException("Parameter " + CONTEXT_PARAM + " cannot be empty");
445+
446+
}
447+
428448
String leadIn = operatorContext.getName(); // .replace('.', '/');
429-
if (staticContext != null && leadIn.indexOf('.') != -1) {
449+
if (ctxName != null && leadIn.indexOf('.') != -1) {
430450
leadIn = leadIn.substring(leadIn.lastIndexOf('.') + 1);
431451
}
432452

@@ -436,10 +456,9 @@ public void registerOperator(ServletOperator operator, Object conduit) throws Ex
436456
operatorContext.getNumberOfStreamingOutputs() != 0) {
437457

438458
String portsContextPath = "/" + leadIn + "/ports";
439-
if (staticContext != null)
440-
portsContextPath = staticContext.getContextPath() + portsContextPath;
441-
ports = new ServletContextHandler(server, portsContextPath,
442-
ServletContextHandler.SESSIONS);
459+
if (ctxName != null)
460+
portsContextPath = "/" + ctxName + portsContextPath;
461+
ports = new ServletContextHandler(server, portsContextPath, ServletContextHandler.SESSIONS);
443462

444463
ports.setAttribute("operator.context", operatorContext);
445464
if (conduit != null)
@@ -480,10 +499,10 @@ public void registerOperator(ServletOperator operator, Object conduit) throws Ex
480499
addHandler(ports);
481500
}
482501

483-
public static class OperatorWebAppContext extends WebAppContext {
502+
/*public static class OperatorWebAppContext extends WebAppContext {
484503
public OperatorWebAppContext() {
485504
}
486-
}
505+
}*/
487506

488507
@Override
489508
public void postDeregister() {

com.ibm.streamsx.inetserver/impl/java/src/com/ibm/streamsx/inet/rest/ops/RequestProcess.java

100755100644
File mode changed.

com.ibm.streamsx.inetserver/impl/java/src/com/ibm/streamsx/inet/rest/ops/ServletOperator.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,18 @@ public void setTrustStorePassword(String ksp) {}
114114

115115
@ContextCheck
116116
public static void checkContextParameters(OperatorContextChecker checker) {
117-
checker.checkDependentParameters("context", "contextResourceBase");
118-
checker.checkDependentParameters("contextResourceBase", "context");
119117

120118
checker.checkDependentParameters(ServletEngine.SSL_CERT_ALIAS_PARAM, ServletEngine.SSL_KEYSTORE_PARAM, ServletEngine.SSL_KEY_PASSWORD_PARAM);
121119
checker.checkDependentParameters(ServletEngine.SSL_KEY_PASSWORD_PARAM, ServletEngine.SSL_CERT_ALIAS_PARAM);
122120
checker.checkDependentParameters(ServletEngine.SSL_KEYSTORE_PASSWORD_PARAM, ServletEngine.SSL_CERT_ALIAS_PARAM);
123121

124122
checker.checkDependentParameters(ServletEngine.SSL_TRUSTSTORE_PARAM, ServletEngine.SSL_CERT_ALIAS_PARAM);
125123
checker.checkDependentParameters(ServletEngine.SSL_TRUSTSTORE_PASSWORD_PARAM, ServletEngine.SSL_TRUSTSTORE_PARAM);
126-
127-
checker.checkDependentParameters(ServletEngine.CONTEXT_PARAM, ServletEngine.CONTEXT_RESOURCE_BASE_PARAM);
124+
128125
checker.checkDependentParameters(ServletEngine.CONTEXT_RESOURCE_BASE_PARAM, ServletEngine.CONTEXT_PARAM);
129126
}
130127

131-
static final String CONTEXT_DESC = "Define a URL context path that maps to the resources defined by" +
128+
static final String CONTEXT_DESC = "Define a URL context path that maps to the resources defined by " +
132129
"`contextResourceBase`. This allows a composite that invokes this operator in a " +
133130
"toolkit to provide resources regardless of the value of the application's data directory. " +
134131
"For example setting it to *maps* would result in the URL */maps/index.html* " +
@@ -159,5 +156,6 @@ public static void checkContextParameters(OperatorContextChecker checker) {
159156
"\\n" +
160157
" param\\n" +
161158
" context: “maps”\\n" +
162-
" contextResourceBase: getThisToolkitDir() + “/opt/resources/mapinfo”\\n";
159+
" contextResourceBase: getThisToolkitDir() + “/opt/resources/mapinfo”\\n\\n" +
160+
"If this parameter is applied parameter `" + ServletEngine.CONTEXT_RESOURCE_BASE_PARAM + "` is required too.";
163161
}

com.ibm.streamsx.inetserver/impl/java/src/com/ibm/streamsx/inet/rest/ops/WebContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
# Licensed Materials - Property of IBM
3-
# Copyright IBM Corp. 2011, 2014
3+
# Copyright IBM Corp. 2011, 2019
44
# US Government Users Restricted Rights - Use, duplication or
55
# disclosure restricted by GSA ADP Schedule Contract with
66
# IBM Corp.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
# Licensed Materials - Property of IBM
3+
# Copyright IBM Corp. 2019, 2020
4+
*/
5+
package com.ibm.streamsx.inet.rest.servlets;
6+
7+
import java.io.IOException;
8+
import java.io.PrintWriter;
9+
import java.util.Map;
10+
11+
import javax.servlet.ServletException;
12+
import javax.servlet.http.HttpServlet;
13+
import javax.servlet.http.HttpServletRequest;
14+
import javax.servlet.http.HttpServletResponse;
15+
16+
import org.eclipse.jetty.servlet.ServletContextHandler;
17+
18+
import com.ibm.json.java.JSONArray;
19+
import com.ibm.json.java.JSONObject;
20+
21+
@SuppressWarnings("serial")
22+
public class ExposedContextInfo extends HttpServlet {
23+
24+
private final Map<String, ServletContextHandler> staticContexts;
25+
26+
public ExposedContextInfo(Map<String, ServletContextHandler> staticContexts) {
27+
this.staticContexts = staticContexts;
28+
}
29+
30+
@Override
31+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
32+
33+
response.setCharacterEncoding("UTF-8");
34+
response.setContentType("application/json");
35+
PrintWriter out = response.getWriter();
36+
response.setStatus(HttpServletResponse.SC_OK);
37+
38+
JSONObject jresp = new JSONObject();
39+
JSONArray jcontexts = new JSONArray();
40+
for (String ctx : staticContexts.keySet()) {
41+
jcontexts.add("/" + ctx);
42+
}
43+
jresp.put("contexts", jcontexts);
44+
out.println(jresp.serialize());
45+
out.flush();
46+
out.close();
47+
}
48+
}

com.ibm.streamsx.inetserver/impl/java/src/com/ibm/streamsx/inet/rest/servlets/InjectWithResponse.java

100755100644
File mode changed.

com.ibm.streamsx.inetserver/impl/java/src/com/ibm/streamsx/inet/rest/servlets/ReqWebMessage.java

100755100644
File mode changed.

0 commit comments

Comments
 (0)