Skip to content

Commit df44a5e

Browse files
committed
Merge branch 'sslcross' into 'release/4.2'
Enable SSL for ItCrossDomainTransactionSecurity See merge request weblogic-cloud/weblogic-kubernetes-operator!4826
2 parents ed8c28b + e4ef37d commit df44a5e

File tree

3 files changed

+219
-20
lines changed

3 files changed

+219
-20
lines changed

integration-tests/src/test/java/oracle/weblogic/kubernetes/ItCrossDomainTransactionSecurity.java

Lines changed: 206 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import java.util.ArrayList;
1212
import java.util.Arrays;
1313
import java.util.Collections;
14+
import java.util.HashMap;
1415
import java.util.List;
16+
import java.util.Map;
1517

1618
import io.kubernetes.client.openapi.models.V1EnvVar;
1719
import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
@@ -30,6 +32,8 @@
3032
import oracle.weblogic.kubernetes.actions.impl.Cluster;
3133
import oracle.weblogic.kubernetes.actions.impl.NginxParams;
3234
import oracle.weblogic.kubernetes.actions.impl.Service;
35+
import oracle.weblogic.kubernetes.actions.impl.primitive.Command;
36+
import oracle.weblogic.kubernetes.actions.impl.primitive.CommandParams;
3337
import oracle.weblogic.kubernetes.actions.impl.primitive.WitParams;
3438
import oracle.weblogic.kubernetes.annotations.IntegrationTest;
3539
import oracle.weblogic.kubernetes.annotations.Namespaces;
@@ -40,6 +44,7 @@
4044
import org.junit.jupiter.api.DisplayName;
4145
import org.junit.jupiter.api.Tag;
4246
import org.junit.jupiter.api.Test;
47+
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
4348

4449
import static java.net.InetAddress.getLocalHost;
4550
import static oracle.weblogic.kubernetes.TestConstants.ADMIN_PASSWORD_DEFAULT;
@@ -77,6 +82,7 @@
7782
import static oracle.weblogic.kubernetes.utils.CommonTestUtils.testUntil;
7883
import static oracle.weblogic.kubernetes.utils.DomainUtils.createDomainAndVerify;
7984
import static oracle.weblogic.kubernetes.utils.FileUtils.copyFileToPod;
85+
import static oracle.weblogic.kubernetes.utils.FileUtils.generateFileFromTemplate;
8086
import static oracle.weblogic.kubernetes.utils.ImageUtils.createTestRepoSecret;
8187
import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.createIngressAndRetryIfFail;
8288
import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx;
@@ -118,6 +124,7 @@ class ItCrossDomainTransactionSecurity {
118124
private static String domain2ManagedServerPrefix = domainUid2 + "-managed-server";
119125
private static LoggingFacade logger = null;
120126
private static int replicaCount = 2;
127+
private static String clusterName = "cluster-2";
121128
private static int t3ChannelPort1 = getNextFreePort();
122129
private static int t3ChannelPort2 = getNextFreePort();
123130
private static String domain1AdminExtSvcRouteHost = null;
@@ -126,6 +133,11 @@ class ItCrossDomainTransactionSecurity {
126133
private static String nginxNamespace = null;
127134
private static NginxParams nginxHelmParams = null;
128135
private static int nginxNodePort;
136+
private static Path tlsCertFile;
137+
private static Path tlsKeyFile;
138+
private static Path jksTrustFile;
139+
private static String tlsSecretName = domainUid2 + "-test-tls-secret";
140+
private static String hostAddress = K8S_NODEPORT_HOST;
129141

130142

131143

@@ -135,7 +147,7 @@ class ItCrossDomainTransactionSecurity {
135147
* JUnit engine parameter resolution mechanism
136148
*/
137149
@BeforeAll
138-
public static void initAll(@Namespaces(3) List<String> namespaces) {
150+
public static void initAll(@Namespaces(3) List<String> namespaces) throws UnknownHostException {
139151
logger = getLogger();
140152

141153
// get a new unique opNamespace
@@ -152,6 +164,7 @@ public static void initAll(@Namespaces(3) List<String> namespaces) {
152164
assertNotNull(namespaces.get(2), "Namespace list is null");
153165
nginxNamespace = namespaces.get(2);
154166

167+
155168
// Create the repo secret to pull the image
156169
// this secret is used only for non-kind cluster
157170
createTestRepoSecret(domainNamespace);
@@ -167,25 +180,6 @@ public static void initAll(@Namespaces(3) List<String> namespaces) {
167180

168181
buildDomains();
169182

170-
}
171-
172-
/**
173-
* Configure two domains d1 and d2 with CrossDomainSecurityEnabled set to true
174-
* On both domains create a user (cross-domain) with group CrossDomainConnectors
175-
* Add required Credential Mapping
176-
* Deploy a JSP on d1's admin server that takes 2 parameteers
177-
* a. The tx aaction b. the d2's cluster service url
178-
* Starts a User transcation
179-
* Send 10 messgaes to a distributed destination (jms.testUniformQueue) on d2 that has 2 members
180-
* Send a message to local destination (jms.admin.adminQueue) on d1
181-
* Commit/rollback the transation
182-
* Receive the messages from the distributed destination (jms.testUniformQueue) on d2
183-
* Receive the message from the local destination (jms.admin.adminQueue) on d1
184-
*/
185-
@Test
186-
@DisplayName("Check cross domain transaction works")
187-
void testCrossDomainTransactionCommitSecurityEnable() throws UnknownHostException {
188-
189183
logger.info("2 domains with crossDomainSecurity enabled start up!");
190184
int domain1AdminServiceNodePort
191185
= getServiceNodePort(domainNamespace, getExternalServicePodName(domain1AdminServerPodName), "default");
@@ -212,7 +206,25 @@ void testCrossDomainTransactionCommitSecurityEnable() throws UnknownHostExceptio
212206
}
213207
logger.info("hostHeader1 for domain1 is: " + hostHeader1);
214208
logger.info("hostAndPort1 for domain1 is: " + hostAndPort1);
209+
}
215210

211+
/**
212+
* Configure two domains d1 and d2 with CrossDomainSecurityEnabled set to true
213+
* On both domains create a user (cross-domain) with group CrossDomainConnectors
214+
* Add required Credential Mapping
215+
* Deploy a JSP on d1's admin server that takes 2 parameteers
216+
* a. The tx action b. the d2's cluster service url
217+
* Starts a User transcation
218+
* Using t3 send 10 messgaes to a distributed destination (jms.testUniformQueue) on d2 that has 2 members
219+
* Using t3 Send a message to local destination (jms.admin.adminQueue) on d1
220+
* Commit/rollback the transation
221+
* Using t3 receive the messages from the distributed destination (jms.testUniformQueue) on d2
222+
* Using t3 receive the message from the local destination (jms.admin.adminQueue) on d1
223+
*/
224+
@Test
225+
@DisplayName("Check cross domain transaction works")
226+
void testCrossDomainTxWithCrossDomainSecurityEnabled() throws UnknownHostException {
227+
216228
// build the standalone JMS Client on Admin pod
217229
String destLocation = "/u01/JmsSendReceiveClient.java";
218230
assertDoesNotThrow(() -> copyFileToPod(domainNamespace,
@@ -294,6 +306,122 @@ void testCrossDomainTransactionCommitSecurityEnable() throws UnknownHostExceptio
294306
"Wait for JMS Client to send/recv msg");
295307
}
296308

309+
/**
310+
* Configure two domains d1 and d2 with CrossDomainSecurityEnabled set to true
311+
* On both domains create a user (cross-domain) with group CrossDomainConnectors
312+
* Add required Credential Mapping
313+
* Deploy a JSP on d1's admin server that takes 2 parameteers
314+
* a. The tx action b. the d2's cluster service url
315+
* Starts a User transcation
316+
* Using t3s send 10 messgaes to a distributed destination (jms.testUniformQueue) on d2 that has 2 members
317+
* Using t3s Send a message to local destination (jms.admin.adminQueue) on d1
318+
* Commit/rollback the transation
319+
* Using t3s receive the messages from the distributed destination (jms.testUniformQueue) on d2
320+
* Using t3s Receive the message from the local destination (jms.admin.adminQueue) on d1
321+
*/
322+
@Test
323+
@DisplayName("Check cross domain transaction works when SSL enabled")
324+
@DisabledIfEnvironmentVariable(named = "OKE_CLUSTER", matches = "true")
325+
void testCrossDomainTxWithCrossDomainSecurityAndSSLEnabled() throws UnknownHostException {
326+
327+
// Create SSL certificate and key using openSSL with SAN extension
328+
createCertKeyFiles(hostAddress);
329+
// Create kubernates secret using genereated certificate and key
330+
createSecretWithTLSCertKey(tlsSecretName);
331+
// Import the tls certificate into a JKS truststote to be used while
332+
// running the standalone client.
333+
importKeytoTrustStore();
334+
335+
//In a UserTransaction send 10 msg to remote udq and 1 msg to local queue and commit the tx
336+
StringBuffer curlCmd1 = new StringBuffer("curl -skg --show-error --noproxy '*' ");
337+
if (TestConstants.KIND_CLUSTER
338+
&& !TestConstants.WLSIMG_BUILDER.equals(TestConstants.WLSIMG_BUILDER_DEFAULT)) {
339+
curlCmd1.append(" -H 'host: " + hostHeader1 + "' ");
340+
}
341+
String url1 = "\"http://" + hostAndPort1
342+
+ "/sample_war/dtx.jsp?remoteurl=t3s://domain2-cluster-cluster-2:8500&action=commit\"";
343+
curlCmd1.append(url1);
344+
logger.info("Executing curl command: {0}", curlCmd1);
345+
assertTrue(getCurlResult(curlCmd1.toString()).contains("Message sent in a commit User Transation"),
346+
"Didn't send expected msg ");
347+
348+
//receive msg from the udq that has 2 memebers
349+
StringBuffer curlCmd2 = new StringBuffer("curl -j --show-error --noproxy '*' ");
350+
if (TestConstants.KIND_CLUSTER
351+
&& !TestConstants.WLSIMG_BUILDER.equals(TestConstants.WLSIMG_BUILDER_DEFAULT)) {
352+
curlCmd2.append(" -H 'host: " + hostHeader1 + "' ");
353+
}
354+
String url2 = "\"http://" + hostAndPort1
355+
+ "/sample_war/get.jsp?remoteurl="
356+
+ "t3s://domain2-cluster-cluster-2:8500&action=recv&dest=jms.testUniformQueue\"";
357+
curlCmd2.append(url2);
358+
logger.info("Executing curl command: {0}", curlCmd2);
359+
for (int i = 0; i < 2; i++) {
360+
assertTrue(getCurlResult(curlCmd2.toString()).contains("Total Message(s) Received : 5"),
361+
"Didn't receive expected msg count from remote queue");
362+
}
363+
364+
// receive 1 msg from the local queue
365+
logger.info("Receiving 1 msg from the local queue");
366+
StringBuffer curlCmdx = new StringBuffer("curl -j --show-error --noproxy '*' ");
367+
if (TestConstants.KIND_CLUSTER
368+
&& !TestConstants.WLSIMG_BUILDER.equals(TestConstants.WLSIMG_BUILDER_DEFAULT)) {
369+
curlCmdx.append(" -H 'host: " + hostHeader1 + "' ");
370+
}
371+
String urlx = "\"http://" + hostAndPort1
372+
+ "/sample_war/get.jsp?remoteurl="
373+
+ "t3s://domain1-admin-server:7002&action=recv&dest=jms.admin.adminQueue\"";
374+
curlCmdx.append(urlx);
375+
logger.info("Executing curl command for local queue: {0}", curlCmdx);
376+
assertTrue(getCurlResult(curlCmdx.toString()).contains("Total Message(s) Received : 1"),
377+
"Didn't receive expected msg count from local queue");
378+
379+
//In a UserTransaction send 10 msg to remote udq and 1 msg to local queue and rollback the tx
380+
StringBuffer curlCmd3 = new StringBuffer("curl -skg --show-error --noproxy '*' ");
381+
if (TestConstants.KIND_CLUSTER
382+
&& !TestConstants.WLSIMG_BUILDER.equals(TestConstants.WLSIMG_BUILDER_DEFAULT)) {
383+
curlCmd3.append(" -H 'host: " + hostHeader1 + "' ");
384+
}
385+
String url3 = "\"http://" + hostAndPort1
386+
+ "/sample_war/dtx.jsp?remoteurl=t3s://domain2-cluster-cluster-2:8500&action=rollback\"";
387+
curlCmd3.append(url3);
388+
logger.info("Executing curl command: {0}", curlCmd3);
389+
assertTrue(getCurlResult(curlCmd3.toString()).contains("Message sent in a rolled-back User Transation"),
390+
"Didn't send expected msg ");
391+
392+
//receive 0 msg from the udq that has 2 memebers
393+
StringBuffer curlCmd4 = new StringBuffer("curl -j --show-error --noproxy '*' ");
394+
if (TestConstants.KIND_CLUSTER
395+
&& !TestConstants.WLSIMG_BUILDER.equals(TestConstants.WLSIMG_BUILDER_DEFAULT)) {
396+
curlCmd4.append(" -H 'host: " + hostHeader1 + "' ");
397+
}
398+
String url4 = "\"http://" + hostAndPort1
399+
+ "/sample_war/get.jsp?remoteurl="
400+
+ "t3s://domain2-cluster-cluster-2:8500&action=recv&dest=jms.testUniformQueue\"";
401+
curlCmd4.append(url4);
402+
logger.info("Executing curl command: {0}", curlCmd4);
403+
for (int i = 0; i < 2; i++) {
404+
assertTrue(getCurlResult(curlCmd4.toString()).contains("Total Message(s) Received : 0"),
405+
"Didn't receive expected msg count from remote queue");
406+
}
407+
408+
// receive 0 msg from the local queue
409+
logger.info("Receiving 0 msg from the local queue");
410+
StringBuffer curlCmdy = new StringBuffer("curl -j --show-error --noproxy '*' ");
411+
if (TestConstants.KIND_CLUSTER
412+
&& !TestConstants.WLSIMG_BUILDER.equals(TestConstants.WLSIMG_BUILDER_DEFAULT)) {
413+
curlCmdy.append(" -H 'host: " + hostHeader1 + "' ");
414+
}
415+
String urly = "\"http://" + hostAndPort1
416+
+ "/sample_war/get.jsp?remoteurl="
417+
+ "t3s://domain1-admin-server:7002&action=recv&dest=jms.admin.adminQueue\"";
418+
curlCmdy.append(urly);
419+
logger.info("Executing curl command for local queue: {0}", curlCmdy);
420+
assertTrue(getCurlResult(curlCmdx.toString()).contains("Total Message(s) Received : 0"),
421+
"Didn't receive expected msg count from local queue");
422+
423+
}
424+
297425
private static String createAuxImage(String imageName, String imageTag, List<String> wdtModelFile,
298426
String wdtVariableFile) {
299427

@@ -630,5 +758,63 @@ private static void createNginxIngressPathRoutingRules() {
630758
assertTrue(callWebAppAndWaitTillReady(curlCmd, 60));
631759
}
632760

761+
// Create and display SSL certificate and key using openSSL with SAN extension
762+
private static void createCertKeyFiles(String cn) {
763+
764+
Map<String, String> sanConfigTemplateMap = new HashMap<>();
765+
sanConfigTemplateMap.put("INGRESS_HOST", hostAddress);
766+
767+
Path srcFile = Paths.get(RESOURCE_DIR,
768+
"tunneling", "san.config.template.txt");
769+
Path targetFile = assertDoesNotThrow(
770+
() -> generateFileFromTemplate(srcFile.toString(),
771+
"san.config.txt", sanConfigTemplateMap));
772+
logger.info("Generated SAN config file {0}", targetFile);
773+
774+
tlsKeyFile = Paths.get(RESULTS_ROOT, domainNamespace + "-tls.key");
775+
tlsCertFile = Paths.get(RESULTS_ROOT, domainNamespace + "-tls.cert");
776+
String opcmd = "openssl req -x509 -nodes -days 365 -newkey rsa:2048 "
777+
+ "-keyout " + tlsKeyFile + " -out " + tlsCertFile
778+
+ " -subj \"/CN=" + cn + "\" -extensions san"
779+
+ " -config " + Paths.get(RESULTS_ROOT, "san.config.txt");
780+
assertTrue(
781+
Command.withParams(new CommandParams()
782+
.command(opcmd)).execute(), "openssl req command fails");
783+
784+
String opcmd2 = "openssl x509 -in " + tlsCertFile + " -noout -text ";
785+
assertTrue(
786+
Command.withParams(new CommandParams()
787+
.command(opcmd2)).execute(), "openssl list command fails");
788+
}
789+
790+
// Import the certificate into a JKS TrustStore to be used while running
791+
// external JMS client to send message to WebLogic.
792+
private static void importKeytoTrustStore() {
793+
794+
jksTrustFile = Paths.get(RESULTS_ROOT, domainNamespace + "-trust.jks");
795+
String keycmd = "keytool -import -file " + tlsCertFile
796+
+ " --keystore " + jksTrustFile
797+
+ " -storetype jks -storepass password -noprompt ";
798+
assertTrue(
799+
Command.withParams(new CommandParams()
800+
.command(keycmd)).execute(), "keytool import command fails");
801+
802+
String keycmd2 = "keytool -list -keystore " + jksTrustFile
803+
+ " -storepass password -noprompt";
804+
assertTrue(
805+
Command.withParams(new CommandParams()
806+
.command(keycmd2)).execute(), "keytool list command fails");
807+
}
808+
809+
// Create kubernetes secret from the ssl key and certificate
810+
private static void createSecretWithTLSCertKey(String tlsSecretName) {
811+
String kcmd = KUBERNETES_CLI + " create secret tls " + tlsSecretName + " --key "
812+
+ tlsKeyFile + " --cert " + tlsCertFile + " -n " + domainNamespace;
813+
assertTrue(
814+
Command.withParams(new CommandParams()
815+
.command(kcmd)).execute(), KUBERNETES_CLI + " create secret command fails");
816+
}
817+
818+
633819
}
634820

integration-tests/src/test/resources/crossdomsecurity/model.dynamic.wls.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ topology:
3434
Server:
3535
"@@PROP:ADMIN_SERVER_NAME@@":
3636
ListenPort: 7001
37+
SSL:
38+
Enabled: true
39+
ListenPort: 7002
3740
NetworkAccessPoint:
3841
T3Channel:
3942
ListenPort: '@@PROP:T3CHANNELPORT@@'
@@ -43,6 +46,9 @@ topology:
4346
"@@PROP:CLUSTER_NAME@@-template":
4447
Cluster: "@@PROP:CLUSTER_NAME@@"
4548
ListenPort : '@@PROP:MANAGED_SERVER_PORT@@'
49+
SSL:
50+
Enabled: true
51+
ListenPort: 8500
4652
resources:
4753
WebAppContainer:
4854
WeblogicPluginEnabled: true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2024, Oracle and/or its affiliates.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
[req]
5+
distinguished_name=req
6+
[san]
7+
subjectAltName=IP:INGRESS_HOST

0 commit comments

Comments
 (0)