This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch 2.13.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 7be866099cd584e6f807e6f3eb5024f1c95ef57a Author: Peter Palaga <[email protected]> AuthorDate: Fri Oct 28 22:41:15 2022 +0200 Add CXF WS-SecurityPolicy test --- .../cxf-soap/cxf-soap-ws-security-server/pom.xml | 229 +++++++++++++++++++++ .../server/it/PasswordCallbackHandler.java | 55 +++++ .../server/it/WsSecurityPolicyServerRoutes.java | 54 +++++ .../server/it/WssSecurityPolicyHelloService.java | 27 +++ .../it/WssSecurityPolicyHelloServiceImpl.java | 39 ++++ .../{application.properties => alice.properties} | 7 +- .../src/main/resources/application.properties | 2 + .../{application.properties => bob.properties} | 7 +- .../src/main/resources/encrypt-sign-policy.xml | 75 +++++++ .../server/it/CxfWssSecurityPolicyServerIT.java | 24 +++ .../server/it/CxfWssSecurityPolicyServerTest.java | 214 +++++++++++++++++++ pom.xml | 1 + poms/build-parent-it/pom.xml | 5 + 13 files changed, 735 insertions(+), 4 deletions(-) diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/pom.xml b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/pom.xml index defb469cf3..72dfc1f8d0 100644 --- a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/pom.xml +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/pom.xml @@ -67,6 +67,235 @@ </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>keytool-maven-plugin</artifactId> + <configuration> + <keypass>password</keypass> + <validity>365</validity> + <keyalg>RSA</keyalg> + <storepass>password</storepass> + </configuration> + <executions> + <execution> + <id>generate-cxfca-keypair</id> + <phase>generate-sources</phase> + <goals> + <goal>clean</goal> + <goal>generateKeyPair</goal> + </goals> + <configuration> + <alias>cxfca</alias> + <dname>CN=cxfca, OU=eng, O=apache.org</dname> + <exts> + <ext>bc:c=ca:true,pathlen:2147483647</ext> + <ext>IssuerAlternativeName=DNS:NOT-FOR-PRODUCTION-USE</ext> + </exts> + <keystore>${project.build.outputDirectory}/cxfca.jks</keystore> + </configuration> + </execution> + <execution> + <id>export-cxfca-certificate</id> + <phase>generate-sources</phase> + <goals> + <goal>exportCertificate</goal> + </goals> + <configuration> + <alias>cxfca</alias> + <keystore>${project.build.outputDirectory}/cxfca.jks</keystore> + <rfc>true</rfc> + <file>${project.build.outputDirectory}/cxfca.pem</file> + </configuration> + </execution> + <execution> + <id>generate-alice-keypair</id> + <phase>generate-sources</phase> + <goals> + <goal>clean</goal> + <goal>generateKeyPair</goal> + </goals> + <configuration> + <alias>alice</alias> + <dname>CN=alice, OU=eng, O=apache.org</dname> + <exts> + <ext>IssuerAlternativeName=DNS:NOT-FOR-PRODUCTION-USE</ext> + <ext>SubjectAlternativeName=DNS:localhost,IP:127.0.0.1</ext> + </exts> + <keystore>${project.build.outputDirectory}/alice.jks</keystore> + </configuration> + </execution> + <execution> + <id>generate-bob-keypair</id> + <phase>generate-sources</phase> + <goals> + <goal>clean</goal> + <goal>generateKeyPair</goal> + </goals> + <configuration> + <alias>bob</alias> + <dname>CN=bob, OU=eng, O=apache.org</dname> + <exts> + <ext>IssuerAlternativeName=DNS:NOT-FOR-PRODUCTION-USE</ext> + <ext>SubjectAlternativeName=DNS:localhost,IP:127.0.0.1</ext> + </exts> + <keystore>${project.build.outputDirectory}/bob.jks</keystore> + </configuration> + </execution> + <execution> + <id>generate-alice-certificate-request</id> + <phase>generate-sources</phase> + <goals> + <goal>generateCertificateRequest</goal> + </goals> + <configuration> + <alias>alice</alias> + <keystore>${project.build.outputDirectory}/alice.jks</keystore> + <file>${project.build.outputDirectory}/alice.csr</file> + </configuration> + </execution> + <execution> + <id>generate-alice-certificate</id> + <phase>generate-sources</phase> + <goals> + <goal>generateCertificate</goal> + </goals> + <configuration> + <alias>cxfca</alias> + <keystore>${project.build.outputDirectory}/cxfca.jks</keystore> + <rfc>true</rfc> + <infile>${project.build.outputDirectory}/alice.csr</infile> + <outfile>${project.build.outputDirectory}/alice.pem</outfile> + </configuration> + </execution> + <execution> + <id>generate-bob-certificate-request</id> + <phase>generate-sources</phase> + <goals> + <goal>generateCertificateRequest</goal> + </goals> + <configuration> + <alias>bob</alias> + <keystore>${project.build.outputDirectory}/bob.jks</keystore> + <file>${project.build.outputDirectory}/bob.csr</file> + </configuration> + </execution> + <execution> + <id>generate-bob-certificate</id> + <phase>generate-sources</phase> + <goals> + <goal>generateCertificate</goal> + </goals> + <configuration> + <alias>cxfca</alias> + <keystore>${project.build.outputDirectory}/cxfca.jks</keystore> + <rfc>true</rfc> + <infile>${project.build.outputDirectory}/bob.csr</infile> + <outfile>${project.build.outputDirectory}/bob.pem</outfile> + </configuration> + </execution> + <execution> + <id>import-cxfca-certificate-to-alice</id> + <phase>generate-sources</phase> + <goals> + <goal>importCertificate</goal> + </goals> + <configuration> + <alias>cxfca</alias> + <trustcacerts>true</trustcacerts> + <noprompt>true</noprompt> + <keystore>${project.build.outputDirectory}/alice.jks</keystore> + <file>${project.build.outputDirectory}/cxfca.pem</file> + </configuration> + </execution> + <execution> + <id>import-cxfca-certificate-to-bob</id> + <phase>generate-sources</phase> + <goals> + <goal>importCertificate</goal> + </goals> + <configuration> + <alias>cxfca</alias> + <trustcacerts>true</trustcacerts> + <noprompt>true</noprompt> + <keystore>${project.build.outputDirectory}/bob.jks</keystore> + <file>${project.build.outputDirectory}/cxfca.pem</file> + </configuration> + </execution> + <execution> + <id>import-alice-certificate</id> + <phase>generate-sources</phase> + <goals> + <goal>importCertificate</goal> + </goals> + <configuration> + <alias>alice</alias> + <trustcacerts>true</trustcacerts> + <noprompt>true</noprompt> + <keystore>${project.build.outputDirectory}/alice.jks</keystore> + <file>${project.build.outputDirectory}/alice.pem</file> + </configuration> + </execution> + <execution> + <id>import-bob-certificate</id> + <phase>generate-sources</phase> + <goals> + <goal>importCertificate</goal> + </goals> + <configuration> + <alias>bob</alias> + <trustcacerts>true</trustcacerts> + <noprompt>true</noprompt> + <keystore>${project.build.outputDirectory}/bob.jks</keystore> + <file>${project.build.outputDirectory}/bob.pem</file> + </configuration> + </execution> + <execution> + <id>import-bob-certificate-to-alice</id> + <phase>generate-sources</phase> + <goals> + <goal>importCertificate</goal> + </goals> + <configuration> + <alias>bob</alias> + <trustcacerts>true</trustcacerts> + <noprompt>true</noprompt> + <keystore>${project.build.outputDirectory}/alice.jks</keystore> + <file>${project.build.outputDirectory}/bob.pem</file> + </configuration> + </execution> + <execution> + <id>import-alice-certificate-to-bob</id> + <phase>generate-sources</phase> + <goals> + <goal>importCertificate</goal> + </goals> + <configuration> + <alias>alice</alias> + <trustcacerts>true</trustcacerts> + <noprompt>true</noprompt> + <keystore>${project.build.outputDirectory}/bob.jks</keystore> + <file>${project.build.outputDirectory}/alice.pem</file> + </configuration> + </execution> +<!-- Uncomment execution block below for local testing --> +<!-- <execution>--> +<!-- <id>list</id>--> +<!-- <phase>generate-sources</phase>--> +<!-- <goals>--> +<!-- <goal>list</goal>--> +<!-- </goals>--> +<!-- <configuration>--> +<!-- <verbose>true</verbose>--> +<!-- <keystore>${project.build.outputDirectory}/bob.jks</keystore>--> +<!-- </configuration>--> +<!-- </execution>--> + </executions> + </plugin> + </plugins> + </build> + <profiles> <profile> <id>native</id> diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/PasswordCallbackHandler.java b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/PasswordCallbackHandler.java new file mode 100644 index 0000000000..73f713a064 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/PasswordCallbackHandler.java @@ -0,0 +1,55 @@ +/* + * 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.quarkus.component.cxf.soap.securitypolicy.server.it; + +import java.io.IOException; +import java.util.Map; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; + +import io.quarkus.runtime.annotations.RegisterForReflection; +import org.apache.wss4j.common.ext.WSPasswordCallback; + +@RegisterForReflection(methods = false, fields = false) +public class PasswordCallbackHandler implements CallbackHandler { + + private final Map<String, String> passwords; + + public PasswordCallbackHandler() { + this.passwords = Map.of( + "alice", "password", + "bob", "password"); + } + + /** + * It attempts to get the password from the private alias/passwords map. + */ + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; + + String pass = passwords.get(pc.getIdentifier()); + if (pass != null) { + pc.setPassword(pass); + return; + } + } + } + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WsSecurityPolicyServerRoutes.java b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WsSecurityPolicyServerRoutes.java new file mode 100644 index 0000000000..f130f41a63 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WsSecurityPolicyServerRoutes.java @@ -0,0 +1,54 @@ +/* + * 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.quarkus.component.cxf.soap.securitypolicy.server.it; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Named; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.cxf.jaxws.CxfEndpoint; +import org.apache.cxf.ext.logging.LoggingFeature; + +@ApplicationScoped +public class WsSecurityPolicyServerRoutes extends RouteBuilder { + + @Override + public void configure() { + + from("cxf:bean:wsSecurityPolicyHelloService?dataFormat=POJO") + .log("exchange: ${exchange}") + .setBody(exchange -> "Secure good morning " + exchange.getMessage().getBody(String.class)); + + } + + @Produces + @ApplicationScoped + @Named + CxfEndpoint wsSecurityPolicyHelloService() { + final CxfEndpoint result = new CxfEndpoint(); + result.setServiceClass(WssSecurityPolicyHelloServiceImpl.class); + result.setAddress("/security-policy-hello"); + + final LoggingFeature lf = new LoggingFeature(); + lf.setPrettyLogging(true); + result.getFeatures().add(lf); + + return result; + } + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WssSecurityPolicyHelloService.java b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WssSecurityPolicyHelloService.java new file mode 100644 index 0000000000..29f2595678 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WssSecurityPolicyHelloService.java @@ -0,0 +1,27 @@ +/* + * 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.quarkus.component.cxf.soap.securitypolicy.server.it; + +import javax.jws.WebMethod; +import javax.jws.WebService; + +@WebService(targetNamespace = "https://quarkiverse.github.io/quarkiverse-docs/quarkus-cxf/ws-securitypolicy") +public interface WssSecurityPolicyHelloService { + + @WebMethod + String sayHello(String name); +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WssSecurityPolicyHelloServiceImpl.java b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WssSecurityPolicyHelloServiceImpl.java new file mode 100644 index 0000000000..632d27451e --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/WssSecurityPolicyHelloServiceImpl.java @@ -0,0 +1,39 @@ +/* + * 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.quarkus.component.cxf.soap.securitypolicy.server.it; + +import javax.jws.WebService; + +import org.apache.cxf.annotations.EndpointProperties; +import org.apache.cxf.annotations.EndpointProperty; +import org.apache.cxf.annotations.Policy; + +@WebService(portName = "EncryptSecurityServicePort", serviceName = "WssSecurityPolicyHelloService", targetNamespace = "https://quarkiverse.github.io/quarkiverse-docs/quarkus-cxf/ws-securitypolicy", endpointInterface = "org.apache.camel.quarkus.component.cxf.soap.securitypolicy.server.it.WssSecurityPolicyHelloService") +@Policy(placement = Policy.Placement.BINDING, uri = "encrypt-sign-policy.xml") +@EndpointProperties(value = { + @EndpointProperty(key = "ws-security.signature.properties", value = "bob.properties"), + @EndpointProperty(key = "ws-security.encryption.properties", value = "bob.properties"), + @EndpointProperty(key = "ws-security.signature.username", value = "bob"), + @EndpointProperty(key = "ws-security.encryption.username", value = "alice"), + @EndpointProperty(key = "ws-security.callback-handler", value = "org.apache.camel.quarkus.component.cxf.soap.securitypolicy.server.it.PasswordCallbackHandler") +}) +public class WssSecurityPolicyHelloServiceImpl implements WssSecurityPolicyHelloService { + + public String sayHello(String name) { + return "Secure Hello " + name + "!"; + } +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/alice.properties similarity index 75% copy from integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties copy to integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/alice.properties index 2eaadf41fb..b562e89eec 100644 --- a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/alice.properties @@ -14,5 +14,8 @@ ## See the License for the specific language governing permissions and ## limitations under the License. ## --------------------------------------------------------------------------- - -quarkus.cxf.path=/soapservice +org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin +org.apache.ws.security.crypto.merlin.keystore.type=jks +org.apache.ws.security.crypto.merlin.keystore.password=password +org.apache.ws.security.crypto.merlin.keystore.alias=alice +org.apache.ws.security.crypto.merlin.file=alice.jks diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties index 2eaadf41fb..7ca94be086 100644 --- a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties @@ -16,3 +16,5 @@ ## --------------------------------------------------------------------------- quarkus.cxf.path=/soapservice + +quarkus.native.resources.includes=bob.properties,alice.properties,alice.jks,bob.jks,encrypt-sign-policy.xml diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/bob.properties similarity index 75% copy from integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties copy to integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/bob.properties index 2eaadf41fb..4b4e1bd8a5 100644 --- a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/application.properties +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/bob.properties @@ -14,5 +14,8 @@ ## See the License for the specific language governing permissions and ## limitations under the License. ## --------------------------------------------------------------------------- - -quarkus.cxf.path=/soapservice +org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin +org.apache.ws.security.crypto.merlin.keystore.type=jks +org.apache.ws.security.crypto.merlin.keystore.password=password +org.apache.ws.security.crypto.merlin.keystore.alias=bob +org.apache.ws.security.crypto.merlin.file=bob.jks \ No newline at end of file diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/encrypt-sign-policy.xml b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/encrypt-sign-policy.xml new file mode 100644 index 0000000000..2eba7ca542 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/main/resources/encrypt-sign-policy.xml @@ -0,0 +1,75 @@ +<?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. + +--> +<wsp:Policy wsu:Id="SecurityServiceEncryptThenSignPolicy" + xmlns:wsp="http://www.w3.org/ns/ws-policy" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" + xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> + <wsp:ExactlyOne> + <wsp:All> + <sp:AsymmetricBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> + <wsp:Policy> + <sp:InitiatorToken> + <wsp:Policy> + <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> + <wsp:Policy> + <sp:WssX509V1Token11/> + </wsp:Policy> + </sp:X509Token> + </wsp:Policy> + </sp:InitiatorToken> + <sp:RecipientToken> + <wsp:Policy> + <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never"> + <wsp:Policy> + <sp:WssX509V1Token11/> + </wsp:Policy> + </sp:X509Token> + </wsp:Policy> + </sp:RecipientToken> + <sp:AlgorithmSuite> + <wsp:Policy> + <sp:Basic256/> + </wsp:Policy> + </sp:AlgorithmSuite> + <sp:Layout> + <wsp:Policy> + <sp:Strict/> + </wsp:Policy> + </sp:Layout> + <sp:IncludeTimestamp/> + <sp:ProtectTokens/> + <sp:OnlySignEntireHeadersAndBody/> + <sp:EncryptBeforeSigning/> + </wsp:Policy> + </sp:AsymmetricBinding> + <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body/> + </sp:SignedParts> + <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <sp:Body/> + </sp:EncryptedParts> + <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> + <wsp:Policy> + <sp:MustSupportRefIssuerSerial/> + </wsp:Policy> + </sp:Wss10> + </wsp:All> + </wsp:ExactlyOne> +</wsp:Policy> diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/test/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/CxfWssSecurityPolicyServerIT.java b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/test/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/CxfWssSecurityPolicyServerIT.java new file mode 100644 index 0000000000..64e2996405 --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/test/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/CxfWssSecurityPolicyServerIT.java @@ -0,0 +1,24 @@ +/* + * 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.quarkus.component.cxf.soap.securitypolicy.server.it; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +public class CxfWssSecurityPolicyServerIT extends CxfWssSecurityPolicyServerTest { + +} diff --git a/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/test/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/CxfWssSecurityPolicyServerTest.java b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/test/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/CxfWssSecurityPolicyServerTest.java new file mode 100644 index 0000000000..7a0fd487bb --- /dev/null +++ b/integration-test-groups/cxf-soap/cxf-soap-ws-security-server/src/test/java/org/apache/camel/quarkus/component/cxf/soap/securitypolicy/server/it/CxfWssSecurityPolicyServerTest.java @@ -0,0 +1,214 @@ +/* + * 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.quarkus.component.cxf.soap.securitypolicy.server.it; + +import java.io.IOException; +import java.util.Map; + +import javax.xml.ws.BindingProvider; + +import io.quarkiverse.cxf.test.QuarkusCxfClientTestUtil; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.config.RestAssuredConfig; +import org.apache.cxf.ws.security.SecurityConstants; +import org.assertj.core.api.Assertions; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; + +import static io.quarkiverse.cxf.test.QuarkusCxfClientTestUtil.anyNs; +import static io.restassured.RestAssured.given; + +@QuarkusTest +public class CxfWssSecurityPolicyServerTest { + + @Test + void encrypetdSigned() throws IOException { + WssSecurityPolicyHelloService client = getPlainClient(); + + Map<String, Object> ctx = ((BindingProvider) client).getRequestContext(); + ctx.put(SecurityConstants.CALLBACK_HANDLER, new PasswordCallbackHandler()); + ctx.put(SecurityConstants.SIGNATURE_PROPERTIES, + Thread.currentThread().getContextClassLoader().getResource("alice.properties")); + ctx.put(SecurityConstants.SIGNATURE_USERNAME, "alice"); + ctx.put(SecurityConstants.ENCRYPT_USERNAME, "bob"); + ctx.put(SecurityConstants.ENCRYPT_PROPERTIES, + Thread.currentThread().getContextClassLoader().getResource("alice.properties")); + + Assertions.assertThat(client.sayHello("foo")).isEqualTo("Secure Hello foo!"); + } + + @Test + void noSecurityConfig() throws IOException { + WssSecurityPolicyHelloService client = getPlainClient(); + /* Make sure that it fails properly when called without a password */ + Assertions.assertThatExceptionOfType(javax.xml.ws.soap.SOAPFaultException.class) + .isThrownBy(() -> client.sayHello("bar")) + .withMessage( + "A encryption username needs to be declared."); + } + + @Test + void unencryptedUnsigned() throws IOException { + final String SOAP_REQUEST = "<soap:Envelope\n" + + " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" + + " <soap:Header/>\n" + + " <soap:Body>\n" + + " <ns2:sayHello\n" + + " xmlns:ns2=\"https://quarkiverse.github.io/quarkiverse-docs/quarkus-cxf/ws-securitypolicy\"/>\n" + + " </soap:Body>\n" + + "</soap:Envelope>"; + + given() + .body(SOAP_REQUEST) + .when().post(QuarkusCxfClientTestUtil.getEndpointUrl(getPlainClient())) + .then() + .statusCode(500) + .body( + Matchers.containsString( + "X509Token: The received token does not match the token inclusion requirement"), + Matchers.containsString("Soap Body is not SIGNED"), + Matchers.containsString("Soap Body is not ENCRYPTED")); + } + + @Test + void fakeSigned() throws IOException { + /* + * A syntactically correct signature, however signed with a different certificate with a different CA than + * deployed on the server + */ + final String SOAP_REQUEST = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" + + " <soap:Header>\n" + + " <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" soap:mustUnderstand=\"1\">\n" + + " <wsse:BinarySecurityToken EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\" wsu:Id=\"X509-53f34474-bcdf-424c-bb90-61b11537cb3f\">MIICnjCCAgmgAwIBAgIEAvQDETALBgkqhkiG9w0BAQUwMzETMBEGA1UEChMKYXBhY2hlLm9yZzEMMAoGA1UECxMDZW5nMQ4wDAYDVQQDEwVjeGZjYTAiGA8yMDIyMDkxOTEyMDA0NFoYDzk5OTkxMjMxMjM1OTU5WjAzMRMwEQYDV [...] + + " <wsu:Timestamp wsu:Id=\"TS-ccfad22e-b376-4349-a625-8896061d6cfd\">\n" + + " <wsu:Created>2022-09-19T12:00:51.226Z</wsu:Created>\n" + + " <wsu:Expires>2022-09-19T12:05:51.226Z</wsu:Expires>\n" + + " </wsu:Timestamp>\n" + + " <xenc:EncryptedKey xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\" Id=\"EK-d77a377b-2dab-4045-ac3e-ea53d7609158\">\n" + + " <xenc:EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p\" />\n" + + " <ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n" + + " <wsse:SecurityTokenReference>\n" + + " <ds:X509Data>\n" + + " <ds:X509IssuerSerial>\n" + + " <ds:X509IssuerName>CN=cxfca,OU=eng,O=apache.org</ds:X509IssuerName>\n" + + " <ds:X509SerialNumber>49546002</ds:X509SerialNumber>\n" + + " </ds:X509IssuerSerial>\n" + + " </ds:X509Data>\n" + + " </wsse:SecurityTokenReference>\n" + + " </ds:KeyInfo>\n" + + " <xenc:CipherData>\n" + + " <xenc:CipherValue>AaHIPkC7xEAxE1WS8u1lwEp8+VVAFhg61EqUyKAxi4jUPRdYXwa1J7jWQ28Z86preNMLJ7CUfv1stESHCziuZtjoundejV588aN7bymBYwN24zu2LRgUQ49PjADInrMX39gqwv9EtgixEUCwkaCS48/ihY7v7Vb7+cXnrpqAcVrxqF8Y0g2/FfN/k/6IZASGORzHKXcszQM9y+QyDzKZvw9ukSj7oDDBNUhrtrhb2KslOC5UukhSkPQwxrIHAlGCmbTDiohhYjEJCzBE9bb1/+0//7vFx/kPuhr8cRI7wg7WAhl8MIUHvv40TD8FoCo8JH1IJSPfuTs+fcLUSSRMBg==</xenc:CipherValue>\n" + + " </xenc:CipherData>\n" + + " </xenc:EncryptedKey>\n" + + " <ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" Id=\"SIG-d48e583c-d310-428b-9541-1c589934b261\">\n" + + " <ds:SignedInfo>\n" + + " <ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\">\n" + + " <ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"soap\" />\n" + + " </ds:CanonicalizationMethod>\n" + + " <ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\" />\n" + + " <ds:Reference URI=\"#TS-ccfad22e-b376-4349-a625-8896061d6cfd\">\n" + + " <ds:Transforms>\n" + + " <ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\">\n" + + " <ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"wsse soap\" />\n" + + " </ds:Transform>\n" + + " </ds:Transforms>\n" + + " <ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" />\n" + + " <ds:DigestValue>pdXC+DtlPCX25Cb1NipeNUOCwl4=</ds:DigestValue>\n" + + " </ds:Reference>\n" + + " <ds:Reference URI=\"#_551cb542-d0fe-4fb8-8e11-e0d7dfe47210\">\n" + + " <ds:Transforms>\n" + + " <ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />\n" + + " </ds:Transforms>\n" + + " <ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" />\n" + + " <ds:DigestValue>LcxYrZK9si3cDmaUurS3dXHKWEI=</ds:DigestValue>\n" + + " </ds:Reference>\n" + + " <ds:Reference URI=\"#X509-53f34474-bcdf-424c-bb90-61b11537cb3f\">\n" + + " <ds:Transforms>\n" + + " <ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\">\n" + + " <ec:InclusiveNamespaces xmlns:ec=\"http://www.w3.org/2001/10/xml-exc-c14n#\" PrefixList=\"soap\" />\n" + + " </ds:Transform>\n" + + " </ds:Transforms>\n" + + " <ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\" />\n" + + " <ds:DigestValue>vDSN64D/q4EjUCBczlIA0IHzxLc=</ds:DigestValue>\n" + + " </ds:Reference>\n" + + " </ds:SignedInfo>\n" + + " <ds:SignatureValue>d2qb4hRGLF/IOJHDA+hiMpil3hEArczDMEq2Q8bzKy74BbAWu54D2d3JWfMceq3/zHNvG4ND7zOd/0o2TPV05i9k5wVya+FOwlP7ibQ/Yy9lkTNhRMHCL94Es63i7AKPwTcTiGJtYQERcUcp4kXaE/fuRlpD4tv2IfnR+ss1jraOqEtgci//xpjWVUBV4vN5Rpolc10QOYUQGjG/ZqaOgT9QHEnm/WN2ZcFMwOrVlc066ifbbHVnJfS/A+VSjoP2FEnNcmRcG8RrNZc4/LOMVCiCnaldriqTrjtCnF29s0Kwtv00P931Yjb4vPFeLIdw6C+zL8/A3q+TOQ4mH9B4MQ==</ds:SignatureValue>\n" + + " <ds:KeyInfo Id=\"KI-2bd212e6-4be5-4d39-b69f-b147f6a540fd\">\n" + + " <wsse:SecurityTokenReference wsu:Id=\"STR-4e477765-3f65-4910-93be-9e1fe3d129a0\">\n" + + " <wsse:Reference URI=\"#X509-53f34474-bcdf-424c-bb90-61b11537cb3f\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3\" />\n" + + " </wsse:SecurityTokenReference>\n" + + " </ds:KeyInfo>\n" + + " </ds:Signature>\n" + + " <xenc:ReferenceList xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\">\n" + + " <xenc:DataReference URI=\"#ED-ed7e9c30-7b36-452d-ac71-85fa51c60986\" />\n" + + " </xenc:ReferenceList>\n" + + " </wsse:Security>\n" + + " </soap:Header>\n" + + " <soap:Body xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"_551cb542-d0fe-4fb8-8e11-e0d7dfe47210\">\n" + + " <xenc:EncryptedData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\" Id=\"ED-ed7e9c30-7b36-452d-ac71-85fa51c60986\" Type=\"http://www.w3.org/2001/04/xmlenc#Content\">\n" + + " <xenc:EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes256-cbc\" />\n" + + " <ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">\n" + + " <wsse:SecurityTokenReference xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsse11=\"http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd\" wsse11:TokenType=\"http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey\">\n" + + " <wsse:Reference URI=\"#EK-d77a377b-2dab-4045-ac3e-ea53d7609158\" />\n" + + " </wsse:SecurityTokenReference>\n" + + " </ds:KeyInfo>\n" + + " <xenc:CipherData>\n" + + " <xenc:CipherValue>21+PWStmrSWFm9QgE0A6hGMEsTAoKFmhLzX2w7MY2B8KCQNeke5eEW7IBXPQySCNgPw7q1+LmOajM/2AmLsKp2q5ZOXxtOStEkJLxbZ4LCsKtv5rfFiWGTl8d7OS8hHGZLVl1wfEG0n/k7FqCw9WRuKfZFqIsQA06yfQPELVU1hUh1K/vEPGGFol4oa1wzVi</xenc:CipherValue>\n" + + " </xenc:CipherData>\n" + + " </xenc:EncryptedData>\n" + + " </soap:Body>\n" + + "</soap:Envelope>"; + + given() + .body(SOAP_REQUEST) + .when().post(QuarkusCxfClientTestUtil.getEndpointUrl(getPlainClient())) + .then() + .statusCode(500) + .body( + Matchers.containsString( + "A security error was encountered when verifying the message")); + } + + /** + * Make sure the policy was included + */ + @Test + void wsdl() { + RestAssuredConfig config = RestAssured.config(); + config.getXmlConfig().namespaceAware(false); + given() + .config(config) + .when().get(QuarkusCxfClientTestUtil.getEndpointUrl(getPlainClient()) + "?wsdl") + .then() + .statusCode(200) + .body( + Matchers.hasXPath( + anyNs("definitions", "Policy") + + "/@*[local-name() = 'Id']", + CoreMatchers.is("SecurityServiceEncryptThenSignPolicy"))); + } + + WssSecurityPolicyHelloService getPlainClient() { + return QuarkusCxfClientTestUtil.getClient( + "https://quarkiverse.github.io/quarkiverse-docs/quarkus-cxf/ws-securitypolicy", + WssSecurityPolicyHelloService.class, + "/soapservice/security-policy-hello"); + } +} diff --git a/pom.xml b/pom.xml index de80f9d7ad..519557394b 100644 --- a/pom.xml +++ b/pom.xml @@ -181,6 +181,7 @@ <groovy.version>3.0.8</groovy.version> <impsort-maven-plugin.version>1.7.0</impsort-maven-plugin.version> <jandex-maven-plugin.version>1.0.8</jandex-maven-plugin.version> + <keytool-maven-plugin.version>1.6</keytool-maven-plugin.version> <mycila-license.version>3.0</mycila-license.version> <maven-assembly-plugin.version>3.1.1</maven-assembly-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> diff --git a/poms/build-parent-it/pom.xml b/poms/build-parent-it/pom.xml index 4d73bb122e..0927ca520e 100644 --- a/poms/build-parent-it/pom.xml +++ b/poms/build-parent-it/pom.xml @@ -107,6 +107,11 @@ <artifactId>camel-servicenow-maven-plugin</artifactId> <version>${camel.version}</version> </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>keytool-maven-plugin</artifactId> + <version>${keytool-maven-plugin.version}</version> + </plugin> </plugins> </pluginManagement> <plugins>
