CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/37c7e0fb Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/37c7e0fb Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/37c7e0fb Branch: refs/heads/master Commit: 37c7e0fbd382456acb361c1f49fe7fbc3ee3323d Parents: 023d5f1 Author: Andrus Adamchik <[email protected]> Authored: Thu Aug 25 12:45:36 2016 +0300 Committer: Andrus Adamchik <[email protected]> Committed: Thu Aug 25 12:45:36 2016 +0300 ---------------------------------------------------------------------- .../cayenne/crypto/Runtime_AES128_Base.java | 39 ++++-- .../cayenne/crypto/Runtime_LazyInit_IT.java | 139 +++++++++++++++++++ .../org/apache/cayenne/crypto/db/Table4.java | 9 ++ .../apache/cayenne/crypto/db/auto/_Table4.java | 36 +++++ .../src/test/resources/datamap.map.xml | 9 ++ 5 files changed, 220 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java index 8703c4a..4b5774c 100644 --- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java @@ -25,29 +25,24 @@ import org.apache.cayenne.test.jdbc.DBHelper; import org.apache.cayenne.test.jdbc.TableHelper; import java.net.URL; +import java.sql.SQLException; public class Runtime_AES128_Base { protected ServerRuntime runtime; protected TableHelper table1; protected TableHelper table2; + protected TableHelper table4; protected void setUp(boolean compress) throws Exception { - URL keyStoreUrl = JceksKeySourceTest.class.getResource(JceksKeySourceTest.KS1_JCEKS); - - CryptoModuleBuilder builder = new CryptoModuleBuilder().keyStore(keyStoreUrl, JceksKeySourceTest.TEST_KEY_PASS, - "k3"); - - if (compress) { - builder.compress(); - } - - Module crypto = builder.build(); + Module crypto = createCryptoModule(compress); + this.runtime = createRuntime(crypto); - this.runtime = new ServerRuntime("cayenne-crypto.xml", crypto); + setupTestTables(new DBHelper(runtime.getDataSource(null))); + } - DBHelper dbHelper = new DBHelper(runtime.getDataSource(null)); + protected void setupTestTables(DBHelper dbHelper) throws SQLException { this.table2 = new TableHelper(dbHelper, "TABLE2").setColumns("ID", "PLAIN_BYTES", "CRYPTO_BYTES"); table2.deleteAll(); @@ -55,6 +50,26 @@ public class Runtime_AES128_Base { this.table1 = new TableHelper(dbHelper, "TABLE1").setColumns("ID", "PLAIN_STRING", "CRYPTO_STRING", "PLAIN_INT", "CRYPTO_INT"); table1.deleteAll(); + + this.table4 = new TableHelper(dbHelper, "TABLE4").setColumns("ID", "PLAIN_STRING", "PLAIN_INT"); + table4.deleteAll(); + } + + protected ServerRuntime createRuntime(Module crypto) { + return new ServerRuntime("cayenne-crypto.xml", crypto); + } + + protected Module createCryptoModule(boolean compress) { + URL keyStoreUrl = JceksKeySourceTest.class.getResource(JceksKeySourceTest.KS1_JCEKS); + + CryptoModuleBuilder builder = new CryptoModuleBuilder().keyStore(keyStoreUrl, JceksKeySourceTest.TEST_KEY_PASS, + "k3"); + + if (compress) { + builder.compress(); + } + + return builder.build(); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java new file mode 100644 index 0000000..bf79489 --- /dev/null +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java @@ -0,0 +1,139 @@ +/***************************************************************** + * 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.cayenne.crypto; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.configuration.server.ServerRuntime; +import org.apache.cayenne.crypto.db.Table1; +import org.apache.cayenne.crypto.db.Table4; +import org.apache.cayenne.crypto.key.KeySource; +import org.apache.cayenne.di.Binder; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.di.Module; +import org.apache.cayenne.query.ObjectSelect; +import org.junit.Before; +import org.junit.Test; + +import java.security.Key; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +public class Runtime_LazyInit_IT extends Runtime_AES128_Base { + + + protected static boolean UNLOCKED; + + @Before + public void before() throws Exception { + setUp(false); + UNLOCKED = false; + } + + @Override + protected ServerRuntime createRuntime(final Module crypto) { + Module cryptoWrapper = new Module() { + @Override + public void configure(Binder binder) { + + crypto.configure(binder); + + binder.decorate(KeySource.class).after(LockingKeySourceDecorator.class); + } + }; + + return super.createRuntime(cryptoWrapper); + } + + @Test + public void testCryptoLocked() { + + assertFalse(UNLOCKED); + + Table4 t4 = runtime.newContext().newObject(Table4.class); + t4.setPlainInt(56); + t4.setPlainString("XX"); + t4.getObjectContext().commitChanges(); + + assertEquals(t4.getObjectId(), ObjectSelect.query(Table4.class).selectOne(runtime.newContext()).getObjectId()); + } + + @Test + public void testCryptoLocked_Unlocked() { + + + assertFalse(UNLOCKED); + + try { + Table1 t1 = runtime.newContext().newObject(Table1.class); + t1.setPlainInt(56); + t1.setCryptoInt(77); + t1.setPlainString("XX"); + t1.setCryptoString("YY"); + t1.getObjectContext().commitChanges(); + + fail("Must have thrown on crypto access"); + } catch (CayenneRuntimeException e) { + // expected + } + + UNLOCKED = true; + + Table1 t1 = runtime.newContext().newObject(Table1.class); + t1.setPlainInt(56); + t1.setCryptoInt(77); + t1.setPlainString("XX"); + t1.setCryptoString("YY"); + t1.getObjectContext().commitChanges(); + + assertEquals(t1.getObjectId(), ObjectSelect.query(Table1.class).selectOne(runtime.newContext()).getObjectId()); + + } + + + public static class LockingKeySourceDecorator implements KeySource { + + private KeySource keySource; + + public LockingKeySourceDecorator(@Inject KeySource keySource) { + this.keySource = keySource; + } + + @Override + public Key getKey(String alias) { + return ensureKeySource().getKey(alias); + } + + @Override + public String getDefaultKeyAlias() { + return ensureKeySource().getDefaultKeyAlias(); + } + + private KeySource ensureKeySource() { + + if (!UNLOCKED) { + throw new IllegalStateException("Crypto is locked"); + } + + return keySource; + } + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java new file mode 100644 index 0000000..89ffe67 --- /dev/null +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java @@ -0,0 +1,9 @@ +package org.apache.cayenne.crypto.db; + +import org.apache.cayenne.crypto.db.auto._Table4; + +public class Table4 extends _Table4 { + + private static final long serialVersionUID = 1L; + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java new file mode 100644 index 0000000..3f825bc --- /dev/null +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java @@ -0,0 +1,36 @@ +package org.apache.cayenne.crypto.db.auto; + +import org.apache.cayenne.CayenneDataObject; +import org.apache.cayenne.exp.Property; + +/** + * Class _Table4 was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public abstract class _Table4 extends CayenneDataObject { + + private static final long serialVersionUID = 1L; + + public static final String ID_PK_COLUMN = "ID"; + + public static final Property<Integer> PLAIN_INT = new Property<Integer>("plainInt"); + public static final Property<String> PLAIN_STRING = new Property<String>("plainString"); + + public void setPlainInt(int plainInt) { + writeProperty("plainInt", plainInt); + } + public int getPlainInt() { + Object value = readProperty("plainInt"); + return (value != null) ? (Integer) value : 0; + } + + public void setPlainString(String plainString) { + writeProperty("plainString", plainString); + } + public String getPlainString() { + return (String)readProperty("plainString"); + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/resources/datamap.map.xml ---------------------------------------------------------------------- diff --git a/cayenne-crypto/src/test/resources/datamap.map.xml b/cayenne-crypto/src/test/resources/datamap.map.xml index 2ea6a80..b71de41 100644 --- a/cayenne-crypto/src/test/resources/datamap.map.xml +++ b/cayenne-crypto/src/test/resources/datamap.map.xml @@ -20,6 +20,11 @@ <db-attribute name="CRYPTO_BYTES" type="VARBINARY"/> <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/> </db-entity> + <db-entity name="TABLE4"> + <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/> + <db-attribute name="PLAIN_INT" type="INTEGER"/> + <db-attribute name="PLAIN_STRING" type="VARCHAR" length="200"/> + </db-entity> <obj-entity name="Table1" className="org.apache.cayenne.crypto.db.Table1" dbEntityName="TABLE1"> <obj-attribute name="cryptoInt" type="int" db-attribute-path="CRYPTO_INT"/> <obj-attribute name="cryptoString" type="java.lang.String" db-attribute-path="CRYPTO_STRING"/> @@ -33,4 +38,8 @@ <obj-entity name="Table3" className="org.apache.cayenne.crypto.db.Table3" dbEntityName="TABLE3"> <obj-attribute name="cryptoString" type="java.lang.String" db-attribute-path="CRYPTO_BYTES"/> </obj-entity> + <obj-entity name="Table4" className="org.apache.cayenne.crypto.db.Table4" dbEntityName="TABLE4"> + <obj-attribute name="plainInt" type="int" db-attribute-path="PLAIN_INT"/> + <obj-attribute name="plainString" type="java.lang.String" db-attribute-path="PLAIN_STRING"/> + </obj-entity> </data-map>
