-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7f982aa
Showing
19 changed files
with
814 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
language: java | ||
jdk: | ||
- oraclejdk7 | ||
- oraclejdk8 | ||
deploy: | ||
provider: releases | ||
api_key: | ||
secure: XRKnP/Pqj7nVUXSzEQqgYmaK63S0La4AM7FneUeApzGaOK5ggK+tk0K5xAqn0zdy9wMZf9gwAZm9qFLsjk6FTnAGGK1IX5KJeljirEQAEbT2uSgMZAOz78F3ODflnbWPK1YeH8ntrfVAA6Opyxqt9To940geFt70bt1GS/8qey7Jn+j8DUKAR9JR4tzPPBFmfqcoI5hN28Q5otI7ztgxrVpsaBtF67Nn8EivdKQgfyXAv9NT0efgjfYo9NYbizsCZ+tXqBkxZ8aIKS0HvvAA5sNhEXLcsRfEh9oFSKnx1Mi3qpR3J64HBOt+SgBaYcp93GxBx8D33zU7rzBs5YWQ+NLSXjWgJVdsqaygcVTZttj7lwDGNvcyl3dsWn9V9M7lhs5sTd1FpqA2R2aHtgD622YQO3j+Oc2dHmu4cj4I/nbXutCRoiuZjsGPsCUv3KxHUKhY0DSU8KOKQ3VjksqUnYRPmpAKmrcFVdMUskKH80oy2RfUZyQFjl4aDAf8SBukWu91zMk0u0ojpJtrlaOdAiqCDUrlpQSIyt0ByvqBgBQhTM+ZIs7qT8IEHaYz93C/EBYox6tmNtPAa67wszz2G0XRqYWfIafASu+OQxjlfdFwP+E4fFy4XGWfF3oIDFkiX1utKgCSYnosiuAYeRYfSO8FloomHCCwZYiTXTRLW7w= | ||
file: target/jmeter-wss-preprocessor-1.0-SNAPSHOT.jar | ||
on: | ||
repo: tilln/jmeter-wss-preprocessor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# jmeter-wss-preprocessor [![travis][travis-image]][travis-url] | ||
|
||
[travis-image]: https://travis-ci.org/tilln/jmeter-wss-preprocessor.svg?branch=master | ||
[travis-url]: https://travis-ci.org/tilln/jmeter-wss-preprocessor | ||
|
||
Overview | ||
------------ | ||
|
||
Apache JMeter plugin for signing and encrypting SOAP messages (WS-Security). | ||
|
||
Installation | ||
------------ | ||
|
||
1. Copy the jmeter-wss-preprocessor jar file into JMeter's lib/ext directory. | ||
2. Copy the following dependencies into JMeter's lib directory: | ||
* [org.apache.wss4j / wss4j-ws-security-dom](http://central.maven.org/maven2/org/apache/wss4j/wss4j-ws-security-common/2.1.8/wss4j-ws-security-common-2.1.8.jar) | ||
* [org.apache.wss4j / wss4j-ws-security-common](http://central.maven.org/maven2/org/apache/wss4j/wss4j-ws-security-common/2.1.8/wss4j-ws-security-common-2.1.8.jar) | ||
* [org.apache.santuario / xmlsec](http://central.maven.org/maven2/org/apache/santuario/xmlsec/2.0.8/xmlsec-2.0.8.jar) | ||
3. When starting JMeter there will be the following two Preprocessors: | ||
SOAP Message Signer | ||
SOAP Message Encrypter | ||
|
||
Usage | ||
------------ | ||
|
||
The plugin provides two [Preprocessors](http://jmeter.apache.org/usermanual/component_reference.html#preprocessors) | ||
that can be configured for signing and encrypting the payloads of an HTTP or JMS request. | ||
Users familiar with SoapUI will find similarities to the [outgoing WS-Security configuration](https://www.soapui.org/soapui-projects/ws-security.html#3-Outgoing-WS-Security-configurations). | ||
|
||
### SOAP Message Signer | ||
|
||
 | ||
|
||
### SOAP Message Encrypter | ||
|
||
 | ||
|
||
|
||
Dependencies | ||
------------ | ||
|
||
Maven retrieves the following dependencies: | ||
|
||
* org.apache.wss4j / wss4j-ws-security-dom | ||
* org.apache.wss4j / wss4j-ws-security-common | ||
* org.apache.santuario / xmlsec |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>co.nz.breakpoint.jmeter.modifiers</groupId> | ||
<artifactId>jmeter-wss-preprocessor</artifactId> | ||
<packaging>jar</packaging> | ||
<version>1.0-SNAPSHOT</version> | ||
<name>jmeter-wss-preprocessor</name> | ||
<url>http://maven.apache.org</url> | ||
|
||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<scm> | ||
<url>https://github.com/tilln/jmeter-wss-preprocessor</url> | ||
<connection>scm:git:git://github.com/tilln/jmeter-wss-preprocessor</connection> | ||
<developerConnection>scm:git:[email protected]:tilln/jmeter-wss-preprocessor.git</developerConnection> | ||
<tag>HEAD</tag> | ||
</scm> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.apache.wss4j</groupId> | ||
<artifactId>wss4j-ws-security-dom</artifactId> | ||
<version>2.1.8</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.jmeter</groupId> | ||
<artifactId>ApacheJMeter_components</artifactId> | ||
<version>3.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.jmeter</groupId> | ||
<artifactId>ApacheJMeter_core</artifactId> | ||
<version>3.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.jmeter</groupId> | ||
<artifactId>ApacheJMeter_http</artifactId> | ||
<version>3.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.jmeter</groupId> | ||
<artifactId>ApacheJMeter_jms</artifactId> | ||
<version>3.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.12</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.6.1</version> | ||
<configuration> | ||
<source>1.7</source> | ||
<target>1.7</target> | ||
<showDeprecation>true</showDeprecation> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-release-plugin</artifactId> | ||
<version>2.5.3</version> | ||
<configuration> | ||
<preparationGoals>clean install</preparationGoals> | ||
<tagNameFormat>@{project.artifactId}-@{project.version}</tagNameFormat> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<version>3.0.2</version> | ||
<configuration> | ||
<finalName>${project.name}-${project.version}</finalName> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
191 changes: 191 additions & 0 deletions
191
src/main/java/nz/co/breakpoint/jmeter/modifiers/AbstractWSSecurityPreProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
package nz.co.breakpoint.jmeter.modifiers; | ||
|
||
import org.apache.jmeter.testelement.AbstractTestElement; | ||
import org.apache.jmeter.processor.PreProcessor; | ||
import org.apache.jmeter.testbeans.TestBean; | ||
import org.apache.jmeter.samplers.Sampler; | ||
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase; | ||
import org.apache.jmeter.protocol.jms.sampler.JMSSampler; | ||
import org.apache.jorphan.logging.LoggingManager; | ||
import org.apache.log.Logger; | ||
import java.io.ByteArrayInputStream; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Properties; | ||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
import javax.xml.parsers.ParserConfigurationException; | ||
import org.apache.wss4j.common.crypto.Crypto; | ||
import org.apache.wss4j.common.crypto.CryptoFactory; | ||
import org.apache.wss4j.common.ext.WSSecurityException; | ||
import org.apache.wss4j.common.util.XMLUtils; | ||
import org.apache.wss4j.dom.message.WSSecHeader; | ||
import org.apache.wss4j.dom.message.WSSecBase; | ||
import org.w3c.dom.Document; | ||
|
||
import static org.apache.wss4j.common.crypto.Merlin.PREFIX; | ||
import static org.apache.wss4j.common.crypto.Merlin.KEYSTORE_FILE; | ||
import static org.apache.wss4j.common.crypto.Merlin.KEYSTORE_PASSWORD; | ||
import static org.apache.wss4j.common.crypto.Merlin.KEYSTORE_TYPE; | ||
|
||
public abstract class AbstractWSSecurityPreProcessor extends AbstractTestElement implements PreProcessor, TestBean { | ||
|
||
private static final Logger log = LoggingManager.getLoggerForClass(); | ||
|
||
private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | ||
static { factory.setNamespaceAware(true); } | ||
|
||
private final DocumentBuilder docBuilder; // Handles the XML document | ||
|
||
protected WSSecBase secBuilder; // Subclasses are to instantiate an appropriate instance | ||
|
||
private final Properties cryptoProps; // Holds configured attributes for crypto instance | ||
|
||
private String certAlias, certPassword; // Certificate alias and password (if private cert) | ||
|
||
static final Map<String, Integer> keyIdentifiers = new HashMap<String, Integer>(); // Subclasses are to populate an appropriate set | ||
|
||
private List<SecurityPart> partsToSecure; // Holds the names of XML elements to secure (e.g. SOAP Body) | ||
|
||
public AbstractWSSecurityPreProcessor() throws ParserConfigurationException { | ||
super(); | ||
docBuilder = factory.newDocumentBuilder(); | ||
cryptoProps = new Properties(); | ||
cryptoProps.setProperty("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin"); | ||
cryptoProps.setProperty(PREFIX+KEYSTORE_TYPE, "jks"); | ||
} | ||
|
||
static String getKeyIdentifierLabelForType(int keyIdentifierType) { | ||
for (Map.Entry<String, Integer> id : keyIdentifiers.entrySet()) { | ||
if (id.getValue() == keyIdentifierType) | ||
return id.getKey(); | ||
} | ||
return null; | ||
} | ||
|
||
protected Sampler getSampler() { | ||
return getThreadContext().getCurrentSampler(); | ||
} | ||
|
||
/* The JMeter API lacks an interface for samplers that have a content or payload, | ||
* so we have to use class specific methods. | ||
*/ | ||
protected String getSamplerContent() { | ||
Sampler sampler = getSampler(); | ||
|
||
if (sampler instanceof HTTPSamplerBase) { | ||
HTTPSamplerBase httpSampler = ((HTTPSamplerBase)sampler); | ||
if (!httpSampler.getPostBodyRaw()) { | ||
log.error("Raw post body required."); | ||
return null; | ||
} | ||
return httpSampler.getArguments().getArgument(0).getValue(); | ||
} | ||
else if (sampler instanceof JMSSampler) { | ||
return ((JMSSampler)sampler).getContent(); | ||
} | ||
log.warn("Cannot get sampler content of "+sampler.getName()); | ||
return null; | ||
} | ||
|
||
protected void setSamplerContent(String content) { | ||
Sampler sampler = getSampler(); | ||
|
||
if (sampler instanceof HTTPSamplerBase) { | ||
((HTTPSamplerBase)sampler).getArguments().getArgument(0).setValue(content); | ||
} | ||
else if (sampler instanceof JMSSampler) { | ||
((JMSSampler)sampler).setContent(content); | ||
} | ||
else { | ||
log.warn("Cannot set sampler content of "+sampler.getName()); | ||
} | ||
} | ||
|
||
/* The main method that is called before the sampler. | ||
* This will get, parse, secure (sign or encrypt) and then replace | ||
* the sampler's payload. | ||
* A new crypto instance needs to be created for every iteration | ||
* as the config could contain variables which may change. | ||
*/ | ||
@Override | ||
public void process() { | ||
String xml = getSamplerContent(); | ||
if (xml == null) return; | ||
|
||
try { | ||
Document doc = docBuilder.parse(new ByteArrayInputStream(xml.getBytes())); | ||
|
||
WSSecHeader secHeader = new WSSecHeader(doc); | ||
secHeader.insertSecurityHeader(); | ||
|
||
Crypto crypto = CryptoFactory.getInstance(cryptoProps); | ||
|
||
doc = this.build(doc, crypto, secHeader); // Delegate in abstract method | ||
|
||
setSamplerContent(XMLUtils.prettyDocumentToString(doc)); | ||
} | ||
catch (Exception e) { | ||
log.error(e.toString()); | ||
} | ||
} | ||
|
||
// Subclasses are to implement the actual creation of the signature or encryption, | ||
// as WSSecBase does not define a build method. | ||
protected abstract Document build(Document document, Crypto crypto, WSSecHeader secHeader) | ||
throws WSSecurityException; | ||
|
||
// Accessors | ||
public String getKeystoreFile() { | ||
return cryptoProps.getProperty(PREFIX+KEYSTORE_FILE); | ||
} | ||
|
||
public void setKeystoreFile(String keystoreFile) { | ||
cryptoProps.setProperty(PREFIX+KEYSTORE_FILE, keystoreFile); | ||
} | ||
|
||
public String getKeystorePassword() { | ||
return cryptoProps.getProperty(PREFIX+KEYSTORE_PASSWORD); | ||
} | ||
|
||
public void setKeystorePassword(String keystorePassword) { | ||
cryptoProps.setProperty(PREFIX+KEYSTORE_PASSWORD, keystorePassword); | ||
} | ||
|
||
public String getCertAlias() { | ||
return certAlias; | ||
} | ||
|
||
public void setCertAlias(String certAlias) { | ||
secBuilder.setUserInfo(this.certAlias = certAlias, certPassword); | ||
} | ||
|
||
public String getCertPassword() { | ||
return certPassword; | ||
} | ||
|
||
public void setCertPassword(String certPassword) { | ||
secBuilder.setUserInfo(certAlias, this.certPassword = certPassword); | ||
} | ||
|
||
public String getKeyIdentifier() { | ||
return getKeyIdentifierLabelForType(secBuilder.getKeyIdentifierType()); | ||
} | ||
|
||
public void setKeyIdentifier(String keyIdentifier) { | ||
secBuilder.setKeyIdentifierType(keyIdentifiers.get(keyIdentifier)); | ||
} | ||
|
||
public List<SecurityPart> getPartsToSecure() { | ||
return partsToSecure; | ||
} | ||
|
||
public void setPartsToSecure(List<SecurityPart> partsToSecure) { | ||
this.partsToSecure = partsToSecure; | ||
secBuilder.getParts().clear(); | ||
for (SecurityPart part : partsToSecure) { | ||
secBuilder.getParts().add(part.getPart()); | ||
} | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/nz/co/breakpoint/jmeter/modifiers/AbstractWSSecurityPreProcessorBeanInfo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package nz.co.breakpoint.jmeter.modifiers; | ||
|
||
import java.beans.PropertyDescriptor; | ||
import org.apache.jmeter.testbeans.BeanInfoSupport; | ||
import org.apache.jmeter.testbeans.gui.FileEditor; | ||
import org.apache.jmeter.testbeans.gui.TableEditor; | ||
import org.apache.jmeter.testbeans.gui.PasswordEditor; | ||
|
||
public class AbstractWSSecurityPreProcessorBeanInfo extends BeanInfoSupport { | ||
|
||
public AbstractWSSecurityPreProcessorBeanInfo(Class<? extends AbstractWSSecurityPreProcessor> clazz) { | ||
super(clazz); | ||
|
||
createPropertyGroup("Certificate", new String[]{ | ||
"keystoreFile", "keystorePassword", "certAlias", "certPassword" | ||
}); | ||
PropertyDescriptor p; | ||
|
||
p = property("keystoreFile"); | ||
p.setPropertyEditorClass(FileEditor.class); | ||
p.setValue(NOT_UNDEFINED, Boolean.TRUE); | ||
p.setValue(DEFAULT, ""); | ||
|
||
p = property("keystorePassword"); | ||
p.setPropertyEditorClass(PasswordEditor.class); | ||
p.setValue(NOT_UNDEFINED, Boolean.TRUE); | ||
p.setValue(DEFAULT, ""); | ||
|
||
p = property("certAlias"); | ||
p.setValue(NOT_UNDEFINED, Boolean.TRUE); | ||
p.setValue(DEFAULT, ""); | ||
|
||
p = property("certPassword"); | ||
p.setPropertyEditorClass(PasswordEditor.class); | ||
p.setValue(NOT_UNDEFINED, Boolean.TRUE); | ||
p.setValue(DEFAULT, ""); | ||
|
||
p = property(getPartsToSecurePropertyName()); | ||
p.setPropertyEditorClass(TableEditor.class); | ||
p.setValue(TableEditor.CLASSNAME, SecurityPart.class.getName()); | ||
p.setValue(TableEditor.HEADERS, new String[]{"Name", "Namespace", "Encode"}); | ||
p.setValue(TableEditor.OBJECT_PROPERTIES, new String[]{"name", "namespace", "modifier"}); | ||
} | ||
|
||
// Parts should go at the bottom, but then subclasses will have to add the element. | ||
protected String getPartsToSecurePropertyName() { | ||
return "partsToSecure"; | ||
} | ||
} |
Oops, something went wrong.