[jboss-svn-commits] JBL Code SVN: r35183 - in labs/jbossrules/branches/4.0.x: drools-compiler/src/test/resources/org/drools/integrationtests and 3 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sat Sep 18 19:02:50 EDT 2010
Author: tirelli
Date: 2010-09-18 19:02:49 -0400 (Sat, 18 Sep 2010)
New Revision: 35183
Added:
labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/droolsClient.keystore
labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/droolsServer.keystore
labs/jbossrules/branches/4.0.x/drools-compiler/src/test/resources/org/drools/integrationtests/droolsClient.keystore
labs/jbossrules/branches/4.0.x/drools-compiler/src/test/resources/org/drools/integrationtests/droolsServer.keystore
labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/util/KeyStoreHelper.java
labs/jbossrules/branches/4.0.x/drools-core/src/test/java/org/drools/util/KeyStoreHelperTest.java
Modified:
labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/MarshallingTest.java
labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/Package.java
labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/PackageCompilationData.java
Log:
JBRULES-2702: Adding support to sign serialized packages and rulebases.
Modified: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/MarshallingTest.java
===================================================================
--- labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/MarshallingTest.java 2010-09-18 05:21:50 UTC (rev 35182)
+++ labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/MarshallingTest.java 2010-09-18 23:02:49 UTC (rev 35183)
@@ -10,6 +10,7 @@
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.Serializable;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -30,6 +31,7 @@
import org.drools.compiler.PackageBuilder;
import org.drools.rule.Package;
import org.drools.rule.Rule;
+import org.drools.util.KeyStoreHelper;
import org.mvel.ExpressionCompiler;
import org.mvel.ParserContext;
@@ -106,13 +108,14 @@
public void testMVELSerialization() {
String expression = "x";
-
+
ExpressionCompiler compiler = new ExpressionCompiler( expression );
ParserContext ctx = new ParserContext();
- ctx.addImport( "x", int.class );
-
+ ctx.addImport( "x",
+ int.class );
+
Serializable result = compiler.compile( ctx );
-
+
try {
byte[] out = serializeOut( result );
Serializable in = (Serializable) serializeIn( out );
@@ -159,10 +162,14 @@
workingMemory.setGlobal( "list",
new ArrayList() );
- final Person bob = new Person( "bob", "stilton" );
- final Cheese c1 = new Cheese( "stilton", 10 );
- final Cheese c2 = new Cheese( "brie", 8 );
- final Cheese c3 = new Cheese( "stilton", 5 );
+ final Person bob = new Person( "bob",
+ "stilton" );
+ final Cheese c1 = new Cheese( "stilton",
+ 10 );
+ final Cheese c2 = new Cheese( "brie",
+ 8 );
+ final Cheese c3 = new Cheese( "stilton",
+ 5 );
workingMemory.insert( bob );
workingMemory.insert( c1 );
workingMemory.insert( c2 );
@@ -666,13 +673,13 @@
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_1.drl" ) ) );
pkg = serialisePackage( builder.getPackage() );
ruleBase.addPackage( pkg );
-
+
InternalFactHandle stilton2 = (InternalFactHandle) session.insert( new Cheese( "stilton",
- 20 ) );
+ 20 ) );
InternalFactHandle brie2 = (InternalFactHandle) session.insert( new Cheese( "brie",
- 20 ) );
+ 20 ) );
InternalFactHandle brie3 = (InternalFactHandle) session.insert( new Cheese( "brie",
- 30 ) );
+ 30 ) );
session.fireAllRules();
assertEquals( 5,
results.size() );
@@ -699,12 +706,12 @@
*/
public void testSerializeAdd3() throws Exception {
//Create a rulebase, a session, and test it
- RuleBase ruleBase = RuleBaseFactory.newRuleBase( );
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase();
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_0.drl" ) ) );
Package pkg = serialisePackage( builder.getPackage() );
ruleBase.addPackage( pkg );
-
+
List results = new ArrayList();
StatefulSession session = ruleBase.newStatefulSession();
session.setGlobal( "results",
@@ -730,19 +737,23 @@
ruleBase = (RuleBase) serializeIn( serializedRulebase );
session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) );
results = (List) session.getGlobal( "results" );
-
+
builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic3_0.drl" ) ) );
pkg = serialisePackage( builder.getPackage() );
-
+
ruleBase.addPackage( pkg );
-
- InternalFactHandle stilton2 = (InternalFactHandle) session.insert( new Cheese( "stilton", 20 ) );
- InternalFactHandle brie2 = (InternalFactHandle) session.insert( new Cheese( "brie", 20 ) );
- InternalFactHandle bob1 = (InternalFactHandle) session.insert( new Person( "bob", 20 ) );
- InternalFactHandle bob2 = (InternalFactHandle) session.insert( new Person( "bob", 30 ) );
+
+ InternalFactHandle stilton2 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 20 ) );
+ InternalFactHandle brie2 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 20 ) );
+ InternalFactHandle bob1 = (InternalFactHandle) session.insert( new Person( "bob",
+ 20 ) );
+ InternalFactHandle bob2 = (InternalFactHandle) session.insert( new Person( "bob",
+ 30 ) );
session.fireAllRules();
-
+
assertEquals( 4,
results.size() );
assertEquals( stilton2.getObject(),
@@ -754,31 +765,35 @@
serializedSession = null;
serializedRulebase = null;
-
+
serializedSession = serializeOut( session );
serializedRulebase = serializeOut( ruleBase );
-
+
session.dispose();
-
+
// now recreate the rulebase, deserialize the session and test it
ruleBase = (RuleBase) serializeIn( serializedRulebase );
session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) );
results = (List) session.getGlobal( "results" );
-
+
builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_2.drl" ) ) );
pkg = serialisePackage( builder.getPackage() );
ruleBase.addPackage( pkg );
-
- InternalFactHandle stilton3 = (InternalFactHandle) session.insert( new Cheese( "stilton", 40 ) );
- InternalFactHandle brie3 = (InternalFactHandle) session.insert( new Cheese( "brie", 40 ) );
- InternalFactHandle bob3 = (InternalFactHandle) session.insert( new Person( "bob", 40 ) );
- InternalFactHandle bob4 = (InternalFactHandle) session.insert( new Person( "bob", 40 ) );
+
+ InternalFactHandle stilton3 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 40 ) );
+ InternalFactHandle brie3 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 40 ) );
+ InternalFactHandle bob3 = (InternalFactHandle) session.insert( new Person( "bob",
+ 40 ) );
+ InternalFactHandle bob4 = (InternalFactHandle) session.insert( new Person( "bob",
+ 40 ) );
InternalFactHandle addr1 = (InternalFactHandle) session.insert( new Address( "bangalore" ) );
InternalFactHandle addr2 = (InternalFactHandle) session.insert( new Address( "India" ) );
-
+
session.fireAllRules();
-
+
assertEquals( 9,
results.size() );
assertEquals( stilton3.getObject(),
@@ -794,26 +809,30 @@
serializedSession = null;
serializedRulebase = null;
-
+
serializedSession = serializeOut( session );
serializedRulebase = serializeOut( ruleBase );
-
+
session.dispose();
-
+
// now recreate the rulebase, deserialize the session and test it
ruleBase = (RuleBase) serializeIn( serializedRulebase );
session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) );
results = (List) session.getGlobal( "results" );
-
- InternalFactHandle stilton4 = (InternalFactHandle) session.insert( new Cheese( "stilton", 50 ) );
- InternalFactHandle brie4 = (InternalFactHandle) session.insert( new Cheese( "brie", 50 ) );
- InternalFactHandle bob5 = (InternalFactHandle) session.insert( new Person( "bob", 50 ) );
- InternalFactHandle bob6 = (InternalFactHandle) session.insert( new Person( "bob", 50 ) );
+
+ InternalFactHandle stilton4 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 50 ) );
+ InternalFactHandle brie4 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 50 ) );
+ InternalFactHandle bob5 = (InternalFactHandle) session.insert( new Person( "bob",
+ 50 ) );
+ InternalFactHandle bob6 = (InternalFactHandle) session.insert( new Person( "bob",
+ 50 ) );
InternalFactHandle addr3 = (InternalFactHandle) session.insert( new Address( "Tripura" ) );
InternalFactHandle addr4 = (InternalFactHandle) session.insert( new Address( "Agartala" ) );
-
+
session.fireAllRules();
-
+
assertEquals( 14,
results.size() );
assertEquals( stilton4.getObject(),
@@ -829,14 +848,14 @@
serializedSession = null;
serializedRulebase = null;
-
+
serializedSession = serializeOut( session );
serializedRulebase = serializeOut( ruleBase );
-
+
session.dispose();
-
+
}
-
+
/*
* I have tried both the scenarios
* 1. Remove a rule from a pkg.
@@ -849,12 +868,12 @@
public void testSerializeAddRemove_NoClassDefFoundError() throws Exception {
//Create a rulebase, a session, and test it
- RuleBase ruleBase = RuleBaseFactory.newRuleBase( );
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase();
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_0.drl" ) ) );
Package pkg = serialisePackage( builder.getPackage() );
ruleBase.addPackage( pkg );
-
+
List results = new ArrayList();
StatefulSession session = ruleBase.newStatefulSession();
session.setGlobal( "results",
@@ -880,19 +899,23 @@
ruleBase = (RuleBase) serializeIn( serializedRulebase );
session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) );
results = (List) session.getGlobal( "results" );
-
+
builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic3_0.drl" ) ) );
pkg = serialisePackage( builder.getPackage() );
-
+
ruleBase.addPackage( pkg );
-
- InternalFactHandle stilton2 = (InternalFactHandle) session.insert( new Cheese( "stilton", 20 ) );
- InternalFactHandle brie2 = (InternalFactHandle) session.insert( new Cheese( "brie", 20 ) );
- InternalFactHandle bob1 = (InternalFactHandle) session.insert( new Person( "bob", 20 ) );
- InternalFactHandle bob2 = (InternalFactHandle) session.insert( new Person( "bob", 30 ) );
+
+ InternalFactHandle stilton2 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 20 ) );
+ InternalFactHandle brie2 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 20 ) );
+ InternalFactHandle bob1 = (InternalFactHandle) session.insert( new Person( "bob",
+ 20 ) );
+ InternalFactHandle bob2 = (InternalFactHandle) session.insert( new Person( "bob",
+ 30 ) );
session.fireAllRules();
-
+
assertEquals( 4,
results.size() );
assertEquals( stilton2.getObject(),
@@ -904,26 +927,31 @@
serializedSession = null;
serializedRulebase = null;
-
+
serializedSession = serializeOut( session );
serializedRulebase = serializeOut( ruleBase );
-
+
session.dispose();
-
+
// now recreate the rulebase, deserialize the session and test it
ruleBase = (RuleBase) serializeIn( serializedRulebase );
session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) );
results = (List) session.getGlobal( "results" );
-
+
// CASE 1: remove rule
- ruleBase.removeRule("org.drools.test", "like stilton");
-
- InternalFactHandle stilton3 = (InternalFactHandle) session.insert( new Cheese( "stilton", 20 ) );
- InternalFactHandle brie3 = (InternalFactHandle) session.insert( new Cheese( "brie", 20 ) );
- InternalFactHandle bob3 = (InternalFactHandle) session.insert( new Person( "bob", 20 ) );
- InternalFactHandle bob4 = (InternalFactHandle) session.insert( new Person( "bob", 30 ) );
+ ruleBase.removeRule( "org.drools.test",
+ "like stilton" );
+
+ InternalFactHandle stilton3 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 20 ) );
+ InternalFactHandle brie3 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 20 ) );
+ InternalFactHandle bob3 = (InternalFactHandle) session.insert( new Person( "bob",
+ 20 ) );
+ InternalFactHandle bob4 = (InternalFactHandle) session.insert( new Person( "bob",
+ 30 ) );
session.fireAllRules();
-
+
assertEquals( 6,
results.size() );
assertEquals( bob4.getObject(),
@@ -931,65 +959,236 @@
assertEquals( bob3.getObject(),
results.get( 5 ) );
-
// now recreate the rulebase, deserialize the session and test it
ruleBase = (RuleBase) serializeIn( serializedRulebase );
session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) );
results = (List) session.getGlobal( "results" );
-
+
// CASE 2: remove pkg
- ruleBase.removePackage("org.drools.test");
-
- InternalFactHandle stilton4 = (InternalFactHandle) session.insert( new Cheese( "stilton", 20 ) );
- InternalFactHandle brie4 = (InternalFactHandle) session.insert( new Cheese( "brie", 20 ) );
- InternalFactHandle bob5 = (InternalFactHandle) session.insert( new Person( "bob", 20 ) );
- InternalFactHandle bob6 = (InternalFactHandle) session.insert( new Person( "bob", 30 ) );
+ ruleBase.removePackage( "org.drools.test" );
+
+ InternalFactHandle stilton4 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 20 ) );
+ InternalFactHandle brie4 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 20 ) );
+ InternalFactHandle bob5 = (InternalFactHandle) session.insert( new Person( "bob",
+ 20 ) );
+ InternalFactHandle bob6 = (InternalFactHandle) session.insert( new Person( "bob",
+ 30 ) );
session.fireAllRules();
-
+
assertEquals( 6,
results.size() );
assertEquals( bob6.getObject(),
results.get( 4 ) );
assertEquals( bob5.getObject(),
results.get( 5 ) );
-
+
serializedSession = null;
serializedRulebase = null;
-
+
// Now serialize rulebase and session again
serializedRulebase = serializeOut( ruleBase );
serializedSession = serializeOut( session );
-
+
session.dispose();
// Deserialize the rulebase and the session
ruleBase = (RuleBase) serializeIn( serializedRulebase );
- session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) ); // throws java.lang.ClassNotFoundException Exception
+ session = ruleBase.newStatefulSession( new ByteArrayInputStream( serializedSession ) ); // throws java.lang.ClassNotFoundException Exception
results = (List) session.getGlobal( "results" );
-
- InternalFactHandle stilton5 = (InternalFactHandle) session.insert( new Cheese( "stilton", 30 ) );
- InternalFactHandle brie5 = (InternalFactHandle) session.insert( new Cheese( "brie", 30 ) );
- InternalFactHandle bob7 = (InternalFactHandle) session.insert( new Person( "bob", 30 ) );
- InternalFactHandle bob8 = (InternalFactHandle) session.insert( new Person( "bob", 40 ) );
+
+ InternalFactHandle stilton5 = (InternalFactHandle) session.insert( new Cheese( "stilton",
+ 30 ) );
+ InternalFactHandle brie5 = (InternalFactHandle) session.insert( new Cheese( "brie",
+ 30 ) );
+ InternalFactHandle bob7 = (InternalFactHandle) session.insert( new Person( "bob",
+ 30 ) );
+ InternalFactHandle bob8 = (InternalFactHandle) session.insert( new Person( "bob",
+ 40 ) );
session.fireAllRules();
-
+
assertEquals( 8,
results.size() );
assertEquals( bob8.getObject(),
results.get( 6 ) );
assertEquals( bob7.getObject(),
results.get( 7 ) );
-
+
serializedSession = null;
serializedRulebase = null;
-
+
serializedSession = serializeOut( session );
serializedRulebase = serializeOut( ruleBase );
-
- session.dispose();
-
+
+ session.dispose();
+
}
-
+
+ /*
+ * Testing the signature framework
+ */
+ public void testSignedSerialization1() throws Exception {
+ try {
+ setPrivateKeyProperties();
+ setPublicKeyProperties();
+
+ //Compile a package
+ PackageBuilder builder = new PackageBuilder();
+ builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_0.drl" ) ) );
+
+ // Test package serialization/deserialization
+ Package pkg = serialisePackage( builder.getPackage() );
+
+ // Create a rulebase
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+ ruleBase.addPackage( pkg );
+
+ // Test rulebase serialization/deserialization
+ byte[] serializedRulebase = serializeOut( ruleBase );
+ ruleBase = (RuleBase) serializeIn( serializedRulebase );
+ } finally {
+ unsetPrivateKeyProperties();
+ unsetPublicKeyProperties();
+ }
+ }
+
+ /*
+ * Deserializing a signed package without the proper public key
+ * should fail.
+ */
+ public void testSignedSerialization2() throws Exception {
+ try {
+ // set only the serialisation properties, but not the deserialization
+ setPrivateKeyProperties();
+
+ //Compile a package
+ PackageBuilder builder = new PackageBuilder();
+ builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_0.drl" ) ) );
+
+ try {
+ // Test package serialization/deserialization
+ Package pkg = serialisePackage( builder.getPackage() );
+ fail( "Deserialisation should have failed." );
+ } catch ( Exception e ) {
+ // success
+ }
+ } finally {
+ unsetPrivateKeyProperties();
+ }
+ }
+
+ /*
+ * Deserializing a signed rulebase without the proper public key
+ * should fail.
+ */
+ public void testSignedSerialization3() throws Exception {
+ try {
+ // set only the serialisation properties, but not the deserialization
+ setPrivateKeyProperties();
+
+ //Compile a package
+ PackageBuilder builder = new PackageBuilder();
+ builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_0.drl" ) ) );
+
+ // Create a rulebase
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+ ruleBase.addPackage( builder.getPackage() );
+
+ // Test rulebase serialization/deserialization
+ byte[] serializedRulebase = serializeOut( ruleBase );
+
+ try {
+ ruleBase = (RuleBase) serializeIn( serializedRulebase );
+ fail( "Deserialisation should have failed." );
+ } catch ( Exception e ) {
+ // success
+ }
+ } finally {
+ unsetPrivateKeyProperties();
+ }
+ }
+
+ /*
+ * Deserializing an unsigned rulebase should always work
+ */
+ public void testSignedSerialization4() throws Exception {
+ try {
+ // set only the deserialisation properties, but not the serialization
+ setPublicKeyProperties();
+
+ //Compile a package
+ PackageBuilder builder = new PackageBuilder();
+ builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_Dynamic1_0.drl" ) ) );
+
+ // Create a rulebase
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+ ruleBase.addPackage( builder.getPackage() );
+
+ // Test rulebase serialization/deserialization
+ byte[] serializedRulebase = serializeOut( ruleBase );
+
+ try {
+ ruleBase = (RuleBase) serializeIn( serializedRulebase );
+ } catch ( Exception e ) {
+ fail( "Deserialisation should have worked." );
+ e.printStackTrace();
+ }
+ } finally {
+ unsetPublicKeyProperties();
+ }
+ }
+
+ private void setPublicKeyProperties() {
+ // Set the client properties to de-serialise the signed packages
+ URL clientKeyStoreURL = getClass().getResource( "droolsClient.keystore" );
+ System.setProperty( KeyStoreHelper.PROP_PUB_KS_URL,
+ clientKeyStoreURL.toExternalForm() );
+ System.setProperty( KeyStoreHelper.PROP_PUB_KS_PWD,
+ "clientpwd" );
+ System.setProperty( KeyStoreHelper.PROP_PUB_ALIAS,
+ "droolsKey" );
+ }
+
+ private void unsetPublicKeyProperties() {
+ // Un-set the client properties to de-serialise the signed packages
+ System.setProperty( KeyStoreHelper.PROP_PUB_KS_URL,
+ "" );
+ System.setProperty( KeyStoreHelper.PROP_PUB_KS_PWD,
+ "" );
+ System.setProperty( KeyStoreHelper.PROP_PUB_ALIAS,
+ "" );
+ }
+
+ private void setPrivateKeyProperties() {
+ // Set the server properties to serialise the signed packages
+ URL serverKeyStoreURL = getClass().getResource( "droolsServer.keystore" );
+ System.setProperty( KeyStoreHelper.PROP_SIGN,
+ "true" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_KS_URL,
+ serverKeyStoreURL.toExternalForm() );
+ System.setProperty( KeyStoreHelper.PROP_PVT_KS_PWD,
+ "serverpwd" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_ALIAS,
+ "droolsKey" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_PWD,
+ "keypwd" );
+ }
+
+ private void unsetPrivateKeyProperties() {
+ // Un-set the server properties to serialise the signed packages
+ System.setProperty( KeyStoreHelper.PROP_SIGN,
+ "" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_KS_URL,
+ "" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_KS_PWD,
+ "" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_ALIAS,
+ "" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_PWD,
+ "" );
+ }
+
protected RuleBase getRuleBase() throws Exception {
return RuleBaseFactory.newRuleBase( RuleBase.RETEOO,
Added: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/droolsClient.keystore
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/droolsClient.keystore
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/droolsServer.keystore
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/java/org/drools/integrationtests/droolsServer.keystore
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/resources/org/drools/integrationtests/droolsClient.keystore
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/resources/org/drools/integrationtests/droolsClient.keystore
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/resources/org/drools/integrationtests/droolsServer.keystore
===================================================================
(Binary files differ)
Property changes on: labs/jbossrules/branches/4.0.x/drools-compiler/src/test/resources/org/drools/integrationtests/droolsServer.keystore
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Modified: labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/Package.java
===================================================================
--- labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/Package.java 2010-09-18 05:21:50 UTC (rev 35182)
+++ labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/Package.java 2010-09-18 23:02:49 UTC (rev 35183)
@@ -156,8 +156,8 @@
stream.writeBoolean( this.valid );
- // Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
- // a byte[]
+ // Rules must be restored by an ObjectInputStream that can resolve using a given
+ // ClassLoader to handle separately by storing as a byte[]
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
final ObjectOutput out = new ObjectOutputStream( bos );
out.writeObject( this.rules );
Modified: labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/PackageCompilationData.java
===================================================================
--- labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/PackageCompilationData.java 2010-09-18 05:21:50 UTC (rev 35182)
+++ labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/rule/PackageCompilationData.java 2010-09-18 23:02:49 UTC (rev 35183)
@@ -25,8 +25,13 @@
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.security.AccessController;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -35,6 +40,7 @@
import java.util.Map.Entry;
import org.drools.CheckedDroolsException;
+import org.drools.RuleBaseConfiguration;
import org.drools.RuntimeDroolsException;
import org.drools.base.accumulators.JavaAccumulatorFunctionExecutor;
import org.drools.common.DroolsObjectInputStream;
@@ -43,6 +49,7 @@
import org.drools.spi.EvalExpression;
import org.drools.spi.PredicateExpression;
import org.drools.spi.ReturnValueExpression;
+import org.drools.util.KeyStoreHelper;
public class PackageCompilationData
implements
@@ -66,7 +73,7 @@
private transient PackageClassLoader classLoader;
private transient ClassLoader parentClassLoader;
-
+
private boolean dirty;
static {
@@ -92,7 +99,7 @@
this.lineMappings = new HashMap();
this.dirty = false;
}
-
+
public boolean isDirty() {
return this.dirty;
}
@@ -111,17 +118,48 @@
*
*/
public void writeExternal(final ObjectOutput stream) throws IOException {
- stream.writeObject( this.store );
+ KeyStoreHelper helper = new KeyStoreHelper();
+
+ stream.writeBoolean( helper.isSigned() );
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutput out = new ObjectOutputStream( bos );
+ out.writeObject( this.store );
+ byte[] buff = bos.toByteArray();
+ stream.writeObject( buff );
+ if ( helper.isSigned() ) {
+ sign( stream,
+ helper,
+ buff );
+ }
+
stream.writeObject( this.AST );
// Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
// a byte[]
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final ObjectOutput out = new ObjectOutputStream( bos );
+ bos = new ByteArrayOutputStream();
+ out = new ObjectOutputStream( bos );
out.writeObject( this.invokerLookups );
- stream.writeObject( bos.toByteArray() );
+ buff = bos.toByteArray();
+ stream.writeObject( buff );
+ if ( helper.isSigned() ) {
+ sign( stream,
+ helper,
+ buff );
+ }
}
+ private void sign(final ObjectOutput stream,
+ KeyStoreHelper helper,
+ byte[] buff) {
+ try {
+ stream.writeObject( helper.signDataWithPrivateKey( buff ) );
+ } catch ( Exception e ) {
+ throw new RuntimeDroolsException( "Error signing object store: " + e.getMessage(),
+ e );
+ }
+ }
+
/**
* Handles the read serialization of the PackageCompilationData. Patterns in Rules may reference generated data which cannot be serialized by
* default methods. The PackageCompilationData holds a reference to the generated bytecode; which must be restored before any Rules.
@@ -130,25 +168,68 @@
*/
public void readExternal(final ObjectInput stream) throws IOException,
ClassNotFoundException {
+ KeyStoreHelper helper = new KeyStoreHelper();
if ( stream instanceof DroolsObjectInputStream ) {
DroolsObjectInputStream droolsStream = (DroolsObjectInputStream) stream;
initClassLoader( droolsStream.getClassLoader() );
} else {
initClassLoader( Thread.currentThread().getContextClassLoader() );
}
+
+ boolean signed = stream.readBoolean();
+ if( signed && helper.getPubKeyStore() == null ) {
+ throw new RuntimeDroolsException("The package was serialized with a signature. Please configure a public keystore with the public key to check the signature. Deserialization aborted.");
+ }
- this.store = (Map) stream.readObject();
+ // Return the object stored as a byte[]
+ byte[] bytes = (byte[]) stream.readObject();
+ if ( signed ) {
+ checkSignature( stream,
+ helper,
+ bytes );
+ }
+ this.store = (Map) new DroolsObjectInputStream( new ByteArrayInputStream( bytes ),
+ this.classLoader ).readObject();
this.AST = stream.readObject();
// Return the rules stored as a byte[]
- final byte[] bytes = (byte[]) stream.readObject();
-
+ bytes = (byte[]) stream.readObject();
+ if ( signed ) {
+ checkSignature( stream,
+ helper,
+ bytes );
+ }
// Use a custom ObjectInputStream that can resolve against a given classLoader
final DroolsObjectInputStream streamWithLoader = new DroolsObjectInputStream( new ByteArrayInputStream( bytes ),
this.classLoader );
this.invokerLookups = (Map) streamWithLoader.readObject();
}
+ private void checkSignature(final ObjectInput stream,
+ KeyStoreHelper helper,
+ byte[] bytes) throws ClassNotFoundException,
+ IOException {
+ byte[] signature = (byte[]) stream.readObject();
+ try {
+ if ( !helper.checkDataWithPublicKey( bytes,
+ signature ) ) {
+ throw new RuntimeDroolsException( "Signature does not match serialized package. This is a security violation. Deserialisation aborted." );
+ }
+ } catch ( InvalidKeyException e ) {
+ throw new RuntimeDroolsException( "Invalid key checking signature: " + e.getMessage(),
+ e );
+ } catch ( KeyStoreException e ) {
+ throw new RuntimeDroolsException( "Error accessing Key Store: " + e.getMessage(),
+ e );
+ } catch ( NoSuchAlgorithmException e ) {
+ throw new RuntimeDroolsException( "No algorithm available: " + e.getMessage(),
+ e );
+ } catch ( SignatureException e ) {
+ throw new RuntimeDroolsException( "Signature Exception: " + e.getMessage(),
+ e );
+ }
+ }
+
public ClassLoader getClassLoader() {
return this.classLoader;
}
@@ -157,7 +238,7 @@
byte[] bytes = null;
if ( this.store != null ) {
- bytes = ( byte[] ) this.store.get( resourceName );
+ bytes = (byte[]) this.store.get( resourceName );
}
return bytes;
}
Added: labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/util/KeyStoreHelper.java
===================================================================
--- labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/util/KeyStoreHelper.java (rev 0)
+++ labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/util/KeyStoreHelper.java 2010-09-18 23:02:49 UTC (rev 35183)
@@ -0,0 +1,211 @@
+/**
+ *
+ */
+package org.drools.util;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.util.Properties;
+
+import org.drools.RuntimeDroolsException;
+
+/**
+ * A helper class to deal with the key store and signing process during
+ * Serialisation
+ *
+ * This class will read and use the following system properties:
+ *
+ * drools.serialisation.sign = <false|true>
+ * drools.serialisation.private.keyStoreURL = <URL>
+ * drools.serialisation.private.keyStorePwd = <password>
+ * drools.serialisation.private.keyAlias = <key>
+ * drools.serialisation.private.keyPwd = <password>
+ * drools.serialisation.public.keyStoreURL = <URL>
+ * drools.serialisation.public.keyStorePwd = <password>
+ * drools.serialisation.public.keyAlias = <key>
+ *
+ * @author etirelli
+ *
+ */
+public class KeyStoreHelper {
+
+ public static final String PROP_SIGN = "drools.serialisation.sign";
+ public static final String PROP_PVT_KS_URL = "drools.serialisation.private.keyStoreURL";
+ public static final String PROP_PVT_KS_PWD = "drools.serialisation.private.keyStorePwd";
+ public static final String PROP_PVT_ALIAS = "drools.serialisation.private.keyAlias";
+ public static final String PROP_PVT_PWD = "drools.serialisation.private.keyPwd";
+ public static final String PROP_PUB_KS_URL = "drools.serialisation.public.keyStoreURL";
+ public static final String PROP_PUB_KS_PWD = "drools.serialisation.public.keyStorePwd";
+ public static final String PROP_PUB_ALIAS = "drools.serialisation.public.keyAlias";
+
+ private boolean signed;
+ private URL pvtKeyStoreURL;
+ private char[] pvtKeyStorePwd;
+ private String pvtKeyAlias;
+ private char[] pvtKeyPassword;
+ private URL pubKeyStoreURL;
+ private char[] pubKeyStorePwd;
+ private String pubKeyAlias;
+
+ private KeyStore pvtKeyStore;
+ private KeyStore pubKeyStore;
+
+ /**
+ * Creates a KeyStoreHelper and initialises the KeyStore, by loading its entries.
+ *
+ * @throws RuntimeDroolsException in case any error happens when initialising and loading the keystore.
+ */
+ public KeyStoreHelper() {
+ try {
+ Properties prop = System.getProperties();
+ this.signed = Boolean.valueOf( prop.getProperty( PROP_SIGN,
+ "false" ) );
+ String url = prop.getProperty( PROP_PVT_KS_URL,
+ "" );
+ if ( url.length() > 0 ) {
+ this.pvtKeyStoreURL = new URL( url );
+ }
+ this.pvtKeyStorePwd = prop.getProperty( PROP_PVT_KS_PWD,
+ "" ).toCharArray();
+ this.pvtKeyAlias = prop.getProperty( PROP_PVT_ALIAS,
+ "" );
+ this.pvtKeyPassword = prop.getProperty( PROP_PVT_PWD,
+ "" ).toCharArray();
+
+ url = prop.getProperty( PROP_PUB_KS_URL,
+ "" );
+ if ( url.length() > 0 ) {
+ this.pubKeyStoreURL = new URL( url );
+ }
+ this.pubKeyStorePwd = prop.getProperty( PROP_PUB_KS_PWD,
+ "" ).toCharArray();
+ this.pubKeyAlias = prop.getProperty( PROP_PUB_ALIAS,
+ "" );
+ initKeyStore();
+ } catch ( Exception e ) {
+ throw new RuntimeDroolsException( "Error initialising KeyStore: " + e.getMessage(),
+ e );
+ }
+ }
+
+ private void initKeyStore() throws NoSuchAlgorithmException,
+ CertificateException,
+ IOException,
+ KeyStoreException {
+ if ( pvtKeyStoreURL != null ) {
+ this.pvtKeyStore = KeyStore.getInstance( "JKS" );
+ this.pvtKeyStore.load( pvtKeyStoreURL.openStream(),
+ pvtKeyStorePwd );
+ }
+ if ( pubKeyStoreURL != null ) {
+ this.pubKeyStore = KeyStore.getInstance( "JKS" );
+ this.pubKeyStore.load( pubKeyStoreURL.openStream(),
+ pubKeyStorePwd );
+ }
+ }
+
+ /**
+ * Generates the signature for the given byte[] using MD5 with RSA algorithm and the
+ * private key with which this helper was initialised.
+ *
+ * @param data the byte[] of data to be signed
+ *
+ * @return the signature, encrypted with the private key
+ *
+ * @throws UnrecoverableKeyException
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ * @throws SignatureException
+ */
+ public byte[] signDataWithPrivateKey(byte[] data) throws UnrecoverableKeyException,
+ KeyStoreException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ SignatureException {
+ PrivateKey pvtkey = (PrivateKey) pvtKeyStore.getKey( pvtKeyAlias,
+ pvtKeyPassword );
+ Signature sig = Signature.getInstance( "MD5withRSA" );
+ sig.initSign( pvtkey );
+ sig.update( data );
+ return sig.sign();
+ }
+
+ /**
+ * Checks the given byte[] data against the signature, using the
+ * public key with which this helper was initialised and the algorithm
+ * MD5 with RSA.
+ *
+ * @param data the original data that was signed
+ * @param signature the provided signature
+ *
+ * @return true in case the signature matches, false otherwise.
+ *
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ * @throws SignatureException
+ */
+ public boolean checkDataWithPublicKey(byte[] data,
+ byte[] signature) throws KeyStoreException,
+ NoSuchAlgorithmException,
+ InvalidKeyException,
+ SignatureException {
+ Certificate cert = pubKeyStore.getCertificate( pubKeyAlias );
+ Signature sig = Signature.getInstance( "MD5withRSA" );
+ sig.initVerify( cert.getPublicKey() );
+ sig.update( data );
+ return sig.verify( signature );
+ }
+
+ public boolean isSigned() {
+ return signed;
+ }
+
+ public URL getPvtKeyStoreURL() {
+ return pvtKeyStoreURL;
+ }
+
+ public char[] getPvtKeyStorePwd() {
+ return pvtKeyStorePwd;
+ }
+
+ public String getPvtKeyAlias() {
+ return pvtKeyAlias;
+ }
+
+ public char[] getPvtKeyPassword() {
+ return pvtKeyPassword;
+ }
+
+ public URL getPubKeyStoreURL() {
+ return pubKeyStoreURL;
+ }
+
+ public char[] getPubKeyStorePwd() {
+ return pubKeyStorePwd;
+ }
+
+ public String getPubKeyAlias() {
+ return pubKeyAlias;
+ }
+
+ public KeyStore getPvtKeyStore() {
+ return pvtKeyStore;
+ }
+
+ public KeyStore getPubKeyStore() {
+ return pubKeyStore;
+ }
+
+}
Property changes on: labs/jbossrules/branches/4.0.x/drools-core/src/main/java/org/drools/util/KeyStoreHelper.java
___________________________________________________________________
Name: svn:executable
+ *
Added: labs/jbossrules/branches/4.0.x/drools-core/src/test/java/org/drools/util/KeyStoreHelperTest.java
===================================================================
--- labs/jbossrules/branches/4.0.x/drools-core/src/test/java/org/drools/util/KeyStoreHelperTest.java (rev 0)
+++ labs/jbossrules/branches/4.0.x/drools-core/src/test/java/org/drools/util/KeyStoreHelperTest.java 2010-09-18 23:02:49 UTC (rev 35183)
@@ -0,0 +1,58 @@
+package org.drools.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+
+import junit.framework.TestCase;
+
+public class KeyStoreHelperTest extends TestCase {
+
+ public void testSignDataWithPrivateKey() throws UnsupportedEncodingException,
+ UnrecoverableKeyException,
+ InvalidKeyException,
+ KeyStoreException,
+ NoSuchAlgorithmException,
+ SignatureException {
+ // The server signs the data with the private key
+
+ // Set properties to simulate the server
+ URL serverKeyStoreURL = getClass().getResource( "droolsServer.keystore" );
+ System.setProperty( KeyStoreHelper.PROP_SIGN, "true" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_KS_URL, serverKeyStoreURL.toExternalForm() );
+ System.setProperty( KeyStoreHelper.PROP_PVT_KS_PWD, "serverpwd" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_ALIAS, "droolsKey" );
+ System.setProperty( KeyStoreHelper.PROP_PVT_PWD, "keypwd" );
+ KeyStoreHelper serverHelper = new KeyStoreHelper();
+
+ // get some data to sign
+ byte[] data = "Hello World".getBytes( "UTF8" );
+
+ // sign the data
+ byte[] signature = serverHelper.signDataWithPrivateKey( data );
+
+ // now, initialise the client helper
+
+ // Set properties to simulate the client
+ URL clientKeyStoreURL = getClass().getResource( "droolsClient.keystore" );
+ System.setProperty( KeyStoreHelper.PROP_SIGN, "true" );
+ System.setProperty( KeyStoreHelper.PROP_PUB_KS_URL, clientKeyStoreURL.toExternalForm() );
+ System.setProperty( KeyStoreHelper.PROP_PUB_KS_PWD, "clientpwd" );
+ System.setProperty( KeyStoreHelper.PROP_PUB_ALIAS, "droolsKey" );
+ // client needs no password to access the certificate and public key
+ KeyStoreHelper clientHelper = new KeyStoreHelper( );
+
+ // check the signature against the data
+ assertTrue( clientHelper.checkDataWithPublicKey( data,
+ signature ) );
+
+ // check some fake data
+ assertFalse( clientHelper.checkDataWithPublicKey( "fake".getBytes( "UTF8" ),
+ signature ) );
+ }
+
+}
Property changes on: labs/jbossrules/branches/4.0.x/drools-core/src/test/java/org/drools/util/KeyStoreHelperTest.java
___________________________________________________________________
Name: svn:executable
+ *
More information about the jboss-svn-commits
mailing list