You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ff...@apache.org on 2022/11/23 21:32:33 UTC
[camel-spring-boot] 01/02: ✅ CXF Simple JAAS Test (#593)
This is an automated email from the ASF dual-hosted git repository.
ffang pushed a commit to branch camel-spring-boot-3.18.x
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
commit f144eed1d1fd4ae52bdab4dcd03b5ea7ba88e1a6
Author: Federico Mariani <34...@users.noreply.github.com>
AuthorDate: Thu Jul 28 07:33:47 2022 +0200
✅ CXF Simple JAAS Test (#593)
(cherry picked from commit 421e9cfacded78c26384be75c17edb30e27b16ee)
---
components-starter/camel-cxf-soap-starter/pom.xml | 5 +
.../component/cxf/security/GreetingService.java | 25 +++++
.../cxf/security/GreetingServiceImpl.java | 28 +++++
.../cxf/security/jaas/SimpleLoginModule.java | 104 ++++++++++++++++++
.../soap/springboot/WSSUsernameTokenHandler.java | 85 ++++++++++++++
.../cxf/soap/springboot/WSSUsernameTokenTest.java | 122 +++++++++++++++++++++
.../src/test/resources/routes/soap-security.xml | 49 +++++++++
.../src/test/resources/simple-jaas.conf | 19 ++++
.../springboot/MllpMaxConcurrentConsumersTest.java | 2 +-
.../MllpTcpClientProducerConnectionErrorTest.java | 3 -
10 files changed, 438 insertions(+), 4 deletions(-)
diff --git a/components-starter/camel-cxf-soap-starter/pom.xml b/components-starter/camel-cxf-soap-starter/pom.xml
index 614681087ba..11bdee34a66 100644
--- a/components-starter/camel-cxf-soap-starter/pom.xml
+++ b/components-starter/camel-cxf-soap-starter/pom.xml
@@ -45,6 +45,11 @@
<version>${cxf-version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-ws-security</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf-common</artifactId>
diff --git a/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/GreetingService.java b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/GreetingService.java
new file mode 100644
index 00000000000..d6312cc7988
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/GreetingService.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.cxf.security;
+
+import javax.jws.WebService;
+
+@WebService
+public interface GreetingService {
+
+ String greet(String name);
+}
diff --git a/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/GreetingServiceImpl.java b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/GreetingServiceImpl.java
new file mode 100644
index 00000000000..7e84b17865a
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/GreetingServiceImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.cxf.security;
+
+import javax.jws.WebService;
+
+@WebService(endpointInterface = "org.apache.camel.component.cxf.security.GreetingService")
+public class GreetingServiceImpl implements GreetingService {
+
+ @Override
+ public String greet(String name) {
+ return "Hello " + name;
+ }
+}
diff --git a/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/jaas/SimpleLoginModule.java b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/jaas/SimpleLoginModule.java
new file mode 100644
index 00000000000..6d2302d05c8
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/security/jaas/SimpleLoginModule.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.cxf.security.jaas;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * Simple LoginModule which checks plain username and password.
+ */
+@Component
+public class SimpleLoginModule implements LoginModule {
+ private static final Logger LOG = LoggerFactory.getLogger(SimpleLoginModule.class);
+
+ public static final String USERNAME = "admin";
+ public static final String PASSWORD = "admin";
+
+ private CallbackHandler callbackHandler;
+
+ private boolean succeeded = false;
+
+ static {
+ final URL jaasConfig = SimpleLoginModule.class.getClassLoader().getResource("simple-jaas.conf");
+ if (jaasConfig != null) {
+ // Set jaas configuration file
+ System.setProperty("java.security.auth.login.config", jaasConfig.toString());
+ } else {
+ LOG.debug("JAAS configuration doesn't exist.");
+ }
+ }
+
+ public SimpleLoginModule() {
+ }
+
+ public boolean abort() throws LoginException {
+ return false;
+ }
+
+ public boolean commit() throws LoginException {
+ return succeeded;
+ }
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
+ this.callbackHandler = callbackHandler;
+ succeeded = false;
+ }
+
+ public boolean login() throws LoginException {
+ succeeded = false;
+ final Callback[] callbacks = new Callback[2];
+ callbacks[0] = new NameCallback("name:");
+ callbacks[1] = new PasswordCallback("password:", false);
+
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (Exception e) {
+ throw new LoginException("Error with callback processing.");
+ }
+
+ final NameCallback nameCallback = (NameCallback) callbacks[0];
+ final PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];
+
+ final String name = nameCallback.getName();
+ final String password = new String(passwordCallback.getPassword());
+
+ if (USERNAME.equals(name) && PASSWORD.equals(password)) {
+ succeeded = true;
+ } else {
+ throw new FailedLoginException("Sorry! No login for you.");
+ }
+ return succeeded;
+ }
+
+ public boolean logout() throws LoginException {
+ return false;
+ }
+}
diff --git a/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/soap/springboot/WSSUsernameTokenHandler.java b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/soap/springboot/WSSUsernameTokenHandler.java
new file mode 100644
index 00000000000..e5a1bfa36e7
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/soap/springboot/WSSUsernameTokenHandler.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.cxf.soap.springboot;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPHeader;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import java.util.Set;
+
+public class WSSUsernameTokenHandler implements SOAPHandler<SOAPMessageContext> {
+
+ private final String username;
+ private final String password;
+
+ public WSSUsernameTokenHandler(String userName, String password) {
+ this.username = userName;
+ this.password = password;
+ }
+
+ @Override
+ public boolean handleMessage(SOAPMessageContext context) {
+ final Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ if (isRequest.booleanValue()) {
+ try {
+ final SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
+ SOAPHeader header = envelope.getHeader();
+ if (header == null) {
+ header = envelope.addHeader();
+ }
+
+ final SOAPElement securityElement = header.addChildElement("Security", "wsse",
+ "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
+
+ final SOAPElement usernameTokenElement = securityElement.addChildElement("UsernameToken", "wsse");
+ usernameTokenElement.addAttribute(new QName("xmlns:wsu"),
+ "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
+
+ final SOAPElement usernameElement = usernameTokenElement.addChildElement("Username", "wsse");
+ usernameElement.addTextNode(username);
+
+ final SOAPElement passwordElement = usernameTokenElement.addChildElement("Password", "wsse");
+ passwordElement.setAttribute("Type",
+ "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0"
+ + "#PasswordText");
+ passwordElement.addTextNode(password);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean handleFault(SOAPMessageContext context) {
+ return true;
+ }
+
+ @Override
+ public void close(MessageContext context) {
+ }
+
+ @Override
+ public Set<QName> getHeaders() {
+ return null;
+ }
+}
diff --git a/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/soap/springboot/WSSUsernameTokenTest.java b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/soap/springboot/WSSUsernameTokenTest.java
new file mode 100644
index 00000000000..ab3c41e9c3a
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/java/org/apache/camel/component/cxf/soap/springboot/WSSUsernameTokenTest.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.cxf.soap.springboot;
+
+import org.apache.camel.component.cxf.security.GreetingService;
+import org.apache.camel.component.cxf.security.jaas.SimpleLoginModule;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.test.annotation.DirtiesContext;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.HandlerResolver;
+import javax.xml.ws.handler.PortInfo;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(classes = {
+ CamelAutoConfiguration.class,
+ WSSUsernameTokenTest.class,
+ SimpleLoginModule.class
+}
+)
+@ImportResource({
+ "classpath:routes/soap-security.xml"
+})
+public class WSSUsernameTokenTest {
+ private static final Logger LOG = LoggerFactory.getLogger(WSSUsernameTokenTest.class);
+
+ private static final String BAD_PASSWORD = "123";
+
+ private static final URL WSDL_URL;
+
+ static {
+ try {
+ WSDL_URL = new URL("http://localhost:16232/cxf/ws/greeting-service?wsdl");
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static final QName SERVICE_NAME = new QName("http://security.cxf.component.camel.apache.org/",
+ "GreetingServiceImplService");
+
+ private void addWSSUsernameTokenHandler(Service service, final String username, final String password) {
+ // set a handler resolver providing WSSUsernameTokenHandler in the handler chain
+ final HandlerResolver handlerResolver = new HandlerResolver() {
+ @Override
+ public List<Handler> getHandlerChain(PortInfo portInfo) {
+ final ArrayList<Handler> handlerChain = new ArrayList<>();
+ handlerChain.add(new WSSUsernameTokenHandler(username, password));
+ return handlerChain;
+ }
+ };
+ service.setHandlerResolver(handlerResolver);
+ }
+
+ @Test
+ public void testAuthenticationCorrectCredentials() throws Exception {
+ final Service service = Service.create(WSDL_URL, SERVICE_NAME);
+ addWSSUsernameTokenHandler(service, SimpleLoginModule.USERNAME, SimpleLoginModule.PASSWORD);
+ final GreetingService greetingService = service.getPort(GreetingService.class);
+
+ final String reply = greetingService.greet("you");
+ Assertions.assertEquals(reply, "Hello you");
+ }
+
+ @Test
+ public void testAuthenticationIncorrectCredentials() throws Exception {
+ final Service service = Service.create(WSDL_URL, SERVICE_NAME);
+ addWSSUsernameTokenHandler(service, SimpleLoginModule.USERNAME, BAD_PASSWORD);
+ final GreetingService greetingService = service.getPort(GreetingService.class);
+
+ try {
+ greetingService.greet("you");
+ Assertions.fail("Authentication should failed");
+ } catch (Exception e) {
+ Assertions.assertTrue(e.getMessage().contains("Authentication failed"));
+ }
+ }
+
+ @Test
+ public void testAuthenticationMissingCredentials() throws Exception {
+ final Service service = Service.create(WSDL_URL, SERVICE_NAME);
+ final GreetingService greetingService = service.getPort(GreetingService.class);
+
+ try {
+ greetingService.greet("you");
+ Assertions.fail("Authentication should failed");
+ } catch (Exception e) {
+ Assertions.assertTrue(e.getMessage().contains("security error"));
+ }
+ }
+}
diff --git a/components-starter/camel-cxf-soap-starter/src/test/resources/routes/soap-security.xml b/components-starter/camel-cxf-soap-starter/src/test/resources/routes/soap-security.xml
new file mode 100644
index 00000000000..a125fe67d5c
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/resources/routes/soap-security.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:cxf="http://camel.apache.org/schema/cxf/jaxws"
+ xmlns:jaxws="http://cxf.apache.org/jaxws"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://camel.apache.org/schema/cxf/jaxws http://camel.apache.org/schema/cxf/jaxws/camel-cxf.xsd
+ http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
+
+ <jaxws:endpoint id="greetingService" address="http://localhost:16232/cxf/ws/greeting-service" implementor="org.apache.camel.component.cxf.security.GreetingServiceImpl">
+
+ <jaxws:inInterceptors>
+ <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
+ <property name="properties">
+ <map>
+ <entry key="action" value="UsernameToken"/>
+ <entry key="passwordType" value="PasswordText"/>
+ </map>
+ </property>
+ </bean>
+ <bean class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
+ <property name="contextName" value="simple-jaas"/>
+ </bean>
+ </jaxws:inInterceptors>
+
+ <jaxws:properties>
+ <entry key="ws-security.validate.token" value="false"/>
+ </jaxws:properties>
+ </jaxws:endpoint>
+</beans>
diff --git a/components-starter/camel-cxf-soap-starter/src/test/resources/simple-jaas.conf b/components-starter/camel-cxf-soap-starter/src/test/resources/simple-jaas.conf
new file mode 100644
index 00000000000..5c0ae3156d4
--- /dev/null
+++ b/components-starter/camel-cxf-soap-starter/src/test/resources/simple-jaas.conf
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+simple-jaas{
+ org.apache.camel.component.cxf.security.jaas.SimpleLoginModule required;
+};
diff --git a/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpMaxConcurrentConsumersTest.java b/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpMaxConcurrentConsumersTest.java
index 5a29e7c74da..4d7284d0440 100644
--- a/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpMaxConcurrentConsumersTest.java
+++ b/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpMaxConcurrentConsumersTest.java
@@ -47,7 +47,7 @@ import org.apache.camel.test.AvailablePortFinder;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
-@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@DirtiesContext
@CamelSpringBootTest
@SpringBootTest(
classes = {
diff --git a/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpTcpClientProducerConnectionErrorTest.java b/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpTcpClientProducerConnectionErrorTest.java
index 393f0446142..e5e25f1f6a3 100644
--- a/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpTcpClientProducerConnectionErrorTest.java
+++ b/components-starter/camel-mllp-starter/src/test/java/org/apache/camel/component/mllp/springboot/MllpTcpClientProducerConnectionErrorTest.java
@@ -45,12 +45,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.test.annotation.DirtiesContext;
import org.apache.camel.test.AvailablePortFinder;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
-
-@DirtiesContext
@CamelSpringBootTest
@SpringBootTest(
classes = {