/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI 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.openengsb.itests.util;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.containsString;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.PublicKey;
import javax.crypto.SecretKey;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.openengsb.core.api.Event;
import org.openengsb.core.api.remote.MethodResult;
import org.openengsb.core.api.remote.MethodResultMessage;
import org.openengsb.core.api.security.DecryptionException;
import org.openengsb.core.api.security.EncryptionException;
import org.openengsb.core.util.CipherUtils;
import org.openengsb.core.util.DefaultOsgiUtilsService;
import org.openengsb.core.workflow.api.RuleBaseException;
import org.openengsb.core.workflow.api.RuleManager;
import org.openengsb.core.workflow.api.model.RuleBaseElementId;
import org.openengsb.core.workflow.api.model.RuleBaseElementType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Abstracts the general concepts required for remote tests
*/
public class AbstractRemoteTestHelper extends AbstractExamTestHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExamTestHelper.class);
protected static final String METHOD_CALL_STRING = ""
+ "{"
+ " \"classes\": ["
+ " \"java.lang.String\","
+ " \"org.openengsb.core.workflow.api.model.ProcessBag\""
+ " ],"
+ " \"methodName\": \"executeWorkflow\","
+ " \"metaData\": {"
+ " \"serviceId\": \"workflowService\","
+ " \"contextId\": \"foo\""
+ " },"
+ " \"args\": ["
+ " \"simpleFlow\","
+ " {"
+ " }"
+ " ]"
+ "}";
protected static final String VOID_CALL_STRING = ""
+ "{"
+ " \"classes\": ["
+ " \"" + Event.class.getName() + "\""
+ " ],"
+ " \"methodName\": \"onEvent\","
+ " \"metaData\": {"
+ " \"serviceId\": \"auditing-root\","
+ " \"contextId\": \"foo\""
+ " },"
+ " \"args\": ["
+ " { \"name\": \"testMessage\" }"
+ " ]"
+ "}";
protected static final String METHOD_CALL_STRING_FILTER = ""
+ "{"
+ " \"classes\": ["
+ " \"java.lang.String\","
+ " \"org.openengsb.core.workflow.api.model.ProcessBag\""
+ " ],"
+ " \"methodName\": \"executeWorkflow\","
+ " \"metaData\": {"
+ " \"serviceFilter\": \"(objectClass=org.openengsb.core.workflow.api.WorkflowService)\","
+ " \"contextId\": \"foo\""
+ " },"
+ " \"args\": ["
+ " \"simpleFlow\","
+ " {"
+ " }"
+ " ]"
+ "}";
protected static final String METHOD_CALL_WITH_MODEL_PARAMETER = ""
+ "{"
+ " \"classes\": ["
+ " \"org.openengsb.domain.example.model.ExampleRequestModel\""
+ " ],"
+ " \"methodName\": \"doSomethingWithModel\","
+ " \"metaData\": {"
+ " \"serviceId\": \"test\""
+ " },"
+ " \"args\": ["
+ " { \"id\":10, \"name\":\"test\" } ]"
+ "}";
protected static final String METHOD_CALL_WITH_MODEL_INCLUDING_TAIL_PARAMETER = ""
+ "{"
+ " \"classes\": ["
+ " \"org.openengsb.domain.example.model.ExampleRequestModel\""
+ " ],"
+ " \"methodName\": \"doSomethingWithModel\","
+ " \"metaData\": {"
+ " \"serviceId\": \"test\""
+ " },"
+ " \"args\": ["
+ " { \"id\":10, \"name\":\"test\", \"openEngSBModelTail\" :[{ "
+ " \"key\":\"specialKey\", \"value\":\"specialValue\", \"type\":\"java.lang.String\" }] "
+ " } ]"
+ "}";
protected RuleManager ruleManager;
@Before
public void setUp() throws Exception {
ruleManager = getOsgiService(RuleManager.class);
}
protected void additionalJMSSetUp(Logger logger) throws Exception {
addWorkflow("simpleFlow");
String string = null;
while (string == null) {
// TODO OPENENGSB-2097 find a better way than an endless loop
logger.warn("checking for simpleFlow to be present");
string = ruleManager.get(new RuleBaseElementId(RuleBaseElementType.Process, "simpleFlow"));
Thread.sleep(1000);
}
}
protected String getOpenwirePort() throws Exception {
return getConfigProperty("org.openengsb.infrastructure.jms", "openwire");
}
protected DefaultOsgiUtilsService getOsgiUtils() throws Exception {
return new DefaultOsgiUtilsService(getBundleContext());
}
protected void addWorkflow(String workflow) throws IOException, RuleBaseException {
if (ruleManager.get(new RuleBaseElementId(RuleBaseElementType.Process, workflow)) == null) {
InputStream is =
getClass().getClassLoader().getResourceAsStream("rulebase/org/openengsb/" + workflow + ".rf");
String testWorkflow = IOUtils.toString(is);
RuleBaseElementId id = new RuleBaseElementId(RuleBaseElementType.Process, workflow);
ruleManager.add(id, testWorkflow);
IOUtils.closeQuietly(is);
}
}
protected String encryptMessage(String secureRequest, SecretKey sessionKey)
throws EncryptionException, InterruptedException, IOException {
PublicKey publicKey = getPublicKeyFromConfigFile();
String encodedMessage = Base64.encodeBase64String(CipherUtils.encrypt(secureRequest.getBytes(), sessionKey));
String encodedKey = Base64.encodeBase64String(CipherUtils.encrypt(sessionKey.getEncoded(), publicKey));
String encryptedMessage = ""
+ "{"
+ " \"encryptedContent\":\"" + encodedMessage + "\","
+ " \"encryptedKey\":\"" + encodedKey + "\""
+ "}";
return encryptedMessage;
}
protected SecretKey generateSessionKey() {
SecretKey sessionKey =
CipherUtils.generateKey(CipherUtils.DEFAULT_SYMMETRIC_ALGORITHM, CipherUtils.DEFAULT_SYMMETRIC_KEYSIZE);
return sessionKey;
}
protected String prepareRequest(String methodCall, String username, String password) {
String authInfo = ""
+ "{"
+ " \"className\":\"org.openengsb.connector.usernamepassword.Password\","
+ " \"data\":"
+ " {"
+ " \"value\":\"" + password + "\""
+ " }"
+ "}";
String secureRequest = ""
+ "{"
+ " \"callId\":\"12345\","
+ " \"answer\":true,"
+ " \"methodCall\":" + methodCall + ","
+ " \"principal\": \"" + username + "\","
+ " \"credentials\":" + authInfo + ","
+ " \"timestamp\":" + System.currentTimeMillis()
+ "}";
return secureRequest;
}
protected PublicKey getPublicKeyFromConfigFile() throws InterruptedException, IOException {
// FIXME do this properly when OPENENGSB-1597 is resolved
File file = new File(System.getProperty("karaf.home"), "/etc/keys/public.key.data");
while (!file.exists()) {
LOGGER.warn("waiting for public key to be generated in " + file);
Thread.sleep(1000);
}
byte[] keyData;
keyData = FileUtils.readFileToByteArray(file);
PublicKey publicKey = CipherUtils.deserializePublicKey(keyData, CipherUtils.DEFAULT_ASYMMETRIC_ALGORITHM);
return publicKey;
}
protected String decryptResult(SecretKey sessionKey, String result) throws DecryptionException {
byte[] resultData = Base64.decodeBase64(result);
assertThat(result, not(containsString("The answer to life the universe and everything")));
byte[] decryptedResultData = CipherUtils.decrypt(resultData, sessionKey);
result = new String(decryptedResultData);
return result;
}
protected void verifyEncryptedResult(SecretKey sessionKey, String result) throws Exception {
try {
result = decryptResult(sessionKey, result);
} catch (DecryptionException e) {
LOGGER.error("decryption failed.");
LOGGER.error(result);
}
if (!result.contains("The answer to life the universe and everything")) {
MethodResultMessage readValue = new ObjectMapper().readValue(result, MethodResultMessage.class);
MethodResult result2 = readValue.getResult();
if (result2.getType().equals(MethodResult.ReturnType.Exception)) {
LOGGER.error(result2.getArg().toString());
}
assertThat(result, containsString("The answer to life the universe and everything"));
}
}
}