You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ni...@apache.org on 2018/10/05 10:03:44 UTC
[1/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes
#4167.
Repository: ignite
Updated Branches:
refs/heads/master 754c7337d -> aabacfa00
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/yardstick/config/benchmark-multicast-tde.properties
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/benchmark-multicast-tde.properties b/modules/yardstick/config/benchmark-multicast-tde.properties
new file mode 100644
index 0000000..d361ba2
--- /dev/null
+++ b/modules/yardstick/config/benchmark-multicast-tde.properties
@@ -0,0 +1,128 @@
+# 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.
+
+#
+# Contains all multicast benchmarks
+#
+
+now0=`date +'%H%M%S'`
+
+# JVM options.
+JVM_OPTS=${JVM_OPTS}" -DIGNITE_QUIET=false -DENCRYPTION_ENABLED=true"
+
+# Uncomment to enable concurrent garbage collection (GC) if you encounter long GC pauses.
+JVM_OPTS=${JVM_OPTS}" \
+-Xms8g \
+-Xmx8g \
+-Xloggc:./gc${now0}.log \
+-XX:+PrintGCDetails \
+-verbose:gc \
+-XX:+UseParNewGC \
+-XX:+UseConcMarkSweepGC \
+-XX:+PrintGCDateStamps \
+"
+
+#Ignite version
+ver="RELEASE-"
+
+# List of default probes.
+# Add DStatProbe or VmStatProbe if your OS supports it (e.g. if running on Linux).
+BENCHMARK_DEFAULT_PROBES=ThroughputLatencyProbe,PercentileProbe,DStatProbe
+
+# Packages where the specified benchmark is searched by reflection mechanism.
+BENCHMARK_PACKAGES=org.yardstickframework,org.apache.ignite.yardstick
+
+# Flag which indicates to restart the servers before every benchmark execution.
+RESTART_SERVERS=true
+
+# Probe point writer class name.
+# BENCHMARK_WRITER=
+
+# Comma-separated list of the hosts to run BenchmarkServers on.
+SERVER_HOSTS=localhost,localhost,localhost
+
+# Comma-separated list of the hosts to run BenchmarkDrivers on.
+DRIVER_HOSTS=localhost
+
+# Remote username.
+# REMOTE_USER=
+
+# Number of nodes, used to wait for the specified number of nodes to start.
+nodesNum=$((`echo ${SERVER_HOSTS} | tr ',' '\n' | wc -l` + `echo ${DRIVER_HOSTS} | tr ',' '\n' | wc -l`))
+
+# Backups count.
+b=1
+
+# Warmup.
+w=60
+
+# Duration.
+d=300
+
+# Threads count.
+t=64
+
+# Sync mode.
+sm=PRIMARY_SYNC
+
+# Jobs.
+j=10
+
+# Run configuration which contains all benchmarks.
+# Note that each benchmark is set to run for 300 seconds (5 min) with warm-up set to 60 seconds (1 minute).
+CONFIGS="\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgnitePutBenchmark -sn IgniteNode -ds ${ver}atomic-put-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgnitePutGetBenchmark -sn IgniteNode -ds ${ver}atomic-put-get-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgnitePutGetEntryBenchmark -sn IgniteNode -ds ${ver}atomic-put-getEntry-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgnitePutTxImplicitBenchmark -sn IgniteNode -ds ${ver}tx-optimistic-put-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -txc OPTIMISTIC -dn IgnitePutGetTxBenchmark -sn IgniteNode -ds ${ver}tx-optim-repRead-put-get-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -txc OPTIMISTIC -dn IgnitePutGetEntryTxBenchmark -sn IgniteNode -ds ${ver}tx-optim-repRead-put-getEntry-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -txc PESSIMISTIC -dn IgnitePutGetTxBenchmark -sn IgniteNode -ds ${ver}tx-pessim-repRead-put-get-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -txc PESSIMISTIC -dn IgnitePutGetEntryTxBenchmark -sn IgniteNode -ds ${ver}tx-pessim-repRead-put-getEntry-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -txc OPTIMISTIC -txi SERIALIZABLE -dn IgnitePutGetTxBenchmark -sn IgniteNode -ds ${ver}tx-opt-serial-put-get-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -txc OPTIMISTIC -txi SERIALIZABLE -dn IgnitePutGetEntryTxBenchmark -sn IgniteNode -ds ${ver}tx-opt-serial-put-getEntry-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlQueryBenchmark -sn IgniteNode -ds ${ver}sql-query-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlQueryJoinBenchmark -sn IgniteNode -ds ${ver}sql-query-join-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlQueryPutBenchmark -sn IgniteNode -ds ${ver}sql-query-put-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -j ${j} -dn IgniteAffinityCallBenchmark -sn IgniteNode -ds ${ver}affcall-compute-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -j ${j} -dn IgniteApplyBenchmark -sn IgniteNode -ds ${ver}apply-compute-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -j ${j} -dn IgniteBroadcastBenchmark -sn IgniteNode -ds ${ver}broad-compute-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -j ${j} -dn IgniteExecuteBenchmark -sn IgniteNode -ds ${ver}exec-compute-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -j ${j} -dn IgniteRunBenchmark -sn IgniteNode -ds ${ver}run-compute-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgnitePutAllBenchmark -sn IgniteNode -ds ${ver}atomic-putAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgnitePutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-putAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgnitePutAllSerializableTxBenchmark -sn IgniteNode -ds ${ver}tx-putAllSerializable-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgniteSqlMergeAllBenchmark -sn IgniteNode -ds ${ver}sql-merge-all-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteReplaceIndexedValue1Benchmark -sn IgniteNode -ds ${ver}replace-indexed1-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgnitePutIfAbsentIndexedValue1Benchmark -sn IgniteNode -ds ${ver}put-if-absent-indexed1-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlMergeBenchmark -sn IgniteNode -ds ${ver}sql-merge-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlMergeQueryBenchmark -sn IgniteNode -ds ${ver}sql-merge-query-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlMergeIndexedValue1Benchmark -sn IgniteNode -ds ${ver}sql-merge-indexed1-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlMergeIndexedValue2Benchmark -sn IgniteNode -ds ${ver}sql-merge-indexed2-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlMergeIndexedValue8Benchmark -sn IgniteNode -ds ${ver}sql-merge-indexed8-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlInsertIndexedValue1Benchmark -sn IgniteNode -ds ${ver}sql-insert-indexed1-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlInsertIndexedValue2Benchmark -sn IgniteNode -ds ${ver}sql-insert-indexed2-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlInsertIndexedValue8Benchmark -sn IgniteNode -ds ${ver}sql-insert-indexed8-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -r 300000 -dn IgniteSqlDeleteBenchmark -sn IgniteNode -ds ${ver}sql-delete-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlDeleteFilteredBenchmark -sn IgniteNode -ds ${ver}sql-delete-filtered-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlUpdateBenchmark -sn IgniteNode -ds ${ver}sql-update-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -dn IgniteSqlUpdateFilteredBenchmark -sn IgniteNode -ds ${ver}sql-update-filtered-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-optimistic-getAllPutAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC -dn IgniteGetEntriesPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-optimistic-getEntriesPutAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc PESSIMISTIC -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-pessimistic-getAllPutAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc PESSIMISTIC -dn IgniteGetEntriesPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-pessimistic-getEntriesPutAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC -txi SERIALIZABLE -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-opt-serializable-getAllPutAll-${b}-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-tde-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC -txi SERIALIZABLE -dn IgniteGetEntriesPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-opt-serializable-getEntriesPutAll-${b}-backup,\
+"
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/yardstick/config/ignite-base-config.xml
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/ignite-base-config.xml b/modules/yardstick/config/ignite-base-config.xml
index 33a52e6..6db8b6e 100644
--- a/modules/yardstick/config/ignite-base-config.xml
+++ b/modules/yardstick/config/ignite-base-config.xml
@@ -22,8 +22,12 @@
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+ <context:property-placeholder />
+
<bean id="base-ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration" abstract="true">
<property name="peerClassLoadingEnabled" value="false"/>
@@ -37,6 +41,8 @@
<property name="cacheMode" value="PARTITIONED"/>
<property name="atomicityMode" value="ATOMIC"/>
+
+ <property name="encryptionEnabled" value="${ENCRYPTION_ENABLED:false}" />
</bean>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
@@ -46,6 +52,8 @@
<property name="atomicityMode" value="TRANSACTIONAL"/>
+ <property name="encryptionEnabled" value="${ENCRYPTION_ENABLED:false}" />
+
</bean>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
@@ -67,6 +75,8 @@
<value>org.apache.ignite.yardstick.cache.model.Person8</value>
</list>
</property>
+
+ <property name="encryptionEnabled" value="${ENCRYPTION_ENABLED:false}" />
</bean>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
@@ -97,6 +107,8 @@
<value>org.apache.ignite.yardstick.cache.model.Person8</value>
</list>
</property>
+
+ <property name="encryptionEnabled" value="${ENCRYPTION_ENABLED:false}" />
</bean>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
@@ -121,6 +133,8 @@
<value>java.lang.Integer</value>
</list>
</property>
+
+ <property name="encryptionEnabled" value="${ENCRYPTION_ENABLED:false}" />
</bean>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
@@ -129,6 +143,8 @@
<property name="cacheMode" value="PARTITIONED"/>
<property name="atomicityMode" value="TRANSACTIONAL"/>
+
+ <property name="encryptionEnabled" value="${ENCRYPTION_ENABLED:false}" />
</bean>
</list>
</property>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/yardstick/config/ignite-tde-config.xml
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/ignite-tde-config.xml b/modules/yardstick/config/ignite-tde-config.xml
new file mode 100644
index 0000000..28e4598
--- /dev/null
+++ b/modules/yardstick/config/ignite-tde-config.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+ <import resource="ignite-base-config.xml"/>
+
+ <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration" parent="base-ignite.cfg">
+ <property name="discoverySpi">
+ <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+ <property name="ipFinder">
+ <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"/>
+ </property>
+ </bean>
+ </property>
+
+ <property name="encryptionSpi">
+ <bean class="org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi">
+ <property name="keyStorePath" value="tde.jks"/>
+ <property name="keyStorePassword" value="love_sex_god"/>
+ </bean>
+ </property>
+
+ <property name="dataStorageConfiguration" >
+ <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
+ <property name="defaultDataRegionConfiguration">
+ <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
+ <property name="persistenceEnabled" value="true"/>
+ </bean>
+ </property>
+ </bean>
+ </property>
+ </bean>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/yardstick/src/main/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/resources/tde.jks b/modules/yardstick/src/main/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/yardstick/src/main/resources/tde.jks differ
[6/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes
#4167.
Posted by ni...@apache.org.
IGNITE-8485: TDE implementation. - Fixes #4167.
Signed-off-by: Nikolay Izhikov <ni...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/aabacfa0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/aabacfa0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/aabacfa0
Branch: refs/heads/master
Commit: aabacfa00f5fd7ef89c9a5bda7b236ff45ed2ac4
Parents: 754c733
Author: Nikolay Izhikov <ni...@apache.org>
Authored: Fri Oct 5 12:55:06 2018 +0300
Committer: Nikolay Izhikov <ni...@apache.org>
Committed: Fri Oct 5 12:55:06 2018 +0300
----------------------------------------------------------------------
.../JmhKeystoreEncryptionSpiBenchmark.java | 117 +++
.../ignite/codegen/MessageCodeGenerator.java | 2 +
.../configuration/CacheConfiguration.java | 33 +
.../configuration/IgniteConfiguration.java | 27 +
.../apache/ignite/internal/GridComponent.java | 9 +-
.../ignite/internal/GridKernalContext.java | 8 +
.../ignite/internal/GridKernalContextImpl.java | 12 +
.../org/apache/ignite/internal/GridTopic.java | 5 +-
.../apache/ignite/internal/IgniteKernal.java | 2 +
.../ignite/internal/IgniteNodeAttributes.java | 3 +
.../org/apache/ignite/internal/IgnitionEx.java | 4 +
.../communication/GridIoMessageFactory.java | 12 +
.../discovery/GridDiscoveryManager.java | 2 +
.../GenerateEncryptionKeyRequest.java | 142 +++
.../GenerateEncryptionKeyResponse.java | 148 ++++
.../encryption/GridEncryptionManager.java | 864 +++++++++++++++++++
.../ignite/internal/pagemem/PageMemory.java | 6 +
.../pagemem/impl/PageMemoryNoStoreImpl.java | 5 +
.../internal/pagemem/store/PageStore.java | 27 +
.../pagemem/wal/record/EncryptedRecord.java | 60 ++
.../pagemem/wal/record/PageSnapshot.java | 19 +-
.../internal/pagemem/wal/record/WALRecord.java | 8 +-
.../delta/DataPageInsertFragmentRecord.java | 2 +-
.../wal/record/delta/DataPageInsertRecord.java | 2 +-
.../delta/DataPageMvccMarkUpdatedRecord.java | 2 +-
.../DataPageMvccUpdateNewTxStateHintRecord.java | 2 +-
.../DataPageMvccUpdateTxStateHintRecord.java | 2 +-
.../wal/record/delta/DataPageRemoveRecord.java | 2 +-
.../wal/record/delta/DataPageUpdateRecord.java | 2 +-
.../wal/record/delta/InitNewPageRecord.java | 2 +-
.../wal/record/delta/MetaPageAddRootRecord.java | 2 +-
.../wal/record/delta/MetaPageCutRootRecord.java | 2 +-
.../wal/record/delta/MetaPageInitRecord.java | 2 +-
.../delta/MetaPageInitRootInlineRecord.java | 2 +-
.../record/delta/MetaPageInitRootRecord.java | 2 +-
.../wal/record/delta/NewRootInitRecord.java | 3 +-
.../record/delta/PagesListAddPageRecord.java | 2 +-
.../delta/PagesListInitNewPageRecord.java | 4 +-
.../record/delta/TrackingPageDeltaRecord.java | 2 +-
.../IgniteAuthenticationProcessor.java | 16 +-
.../processors/cache/ClusterCachesInfo.java | 34 +-
.../cache/DynamicCacheChangeRequest.java | 17 +
.../processors/cache/GridCacheAttributes.java | 9 +-
.../processors/cache/GridCacheProcessor.java | 135 ++-
.../processors/cache/GridCacheUtils.java | 23 +
.../cache/IgniteCacheOffheapManagerImpl.java | 10 +-
.../GridDhtPartitionsExchangeFuture.java | 2 +
.../processors/cache/mvcc/MvccUtils.java | 3 +-
.../cache/persistence/CacheDataRowAdapter.java | 2 +-
.../cache/persistence/DataStructure.java | 6 +-
.../GridCacheDatabaseSharedManager.java | 3 +
.../persistence/GridCacheOffheapManager.java | 23 +-
.../cache/persistence/file/EncryptedFileIO.java | 371 ++++++++
.../file/EncryptedFileIOFactory.java | 100 +++
.../cache/persistence/file/FilePageStore.java | 28 +-
.../persistence/file/FilePageStoreFactory.java | 3 +-
.../persistence/file/FilePageStoreManager.java | 76 +-
.../file/FileVersionCheckingFactory.java | 25 +-
.../cache/persistence/freelist/PagesList.java | 4 +-
.../persistence/metastorage/MetaStorage.java | 2 +
.../persistence/pagemem/PageMemoryImpl.java | 30 +-
.../cache/persistence/tree/io/BPlusIO.java | 4 +-
.../cache/persistence/tree/io/PageIO.java | 5 +-
.../tree/io/PagePartitionCountersIO.java | 2 +-
.../persistence/tree/util/PageHandler.java | 50 +-
.../wal/reader/StandaloneGridKernalContext.java | 6 +
.../reader/StandaloneWalRecordsIterator.java | 3 +
.../wal/serializer/RecordDataV1Serializer.java | 355 +++++++-
.../wal/serializer/RecordDataV2Serializer.java | 60 +-
.../serializer/RecordSerializerFactoryImpl.java | 5 +-
.../wal/serializer/RecordV1Serializer.java | 8 +-
.../wal/serializer/RecordV2Serializer.java | 2 +-
.../cluster/ChangeGlobalStateMessage.java | 6 +-
.../cluster/GridClusterStateProcessor.java | 2 +
.../utils/PlatformConfigurationUtils.java | 59 ++
.../processors/query/GridQueryProcessor.java | 6 +-
.../ignite/internal/util/IgniteUtils.java | 65 ++
.../ignite/internal/util/lang/GridFunc.java | 6 +-
.../ignite/spi/encryption/EncryptionSpi.java | 113 +++
.../keystore/KeystoreEncryptionKey.java | 84 ++
.../keystore/KeystoreEncryptionSpi.java | 501 +++++++++++
.../spi/encryption/keystore/package-info.java | 22 +
.../spi/encryption/noop/NoopEncryptionSpi.java | 101 +++
.../ignite/spi/encryption/package-info.java | 22 +
.../encryption/AbstractEncryptionTest.java | 245 ++++++
.../encryption/EncryptedCacheBigEntryTest.java | 114 +++
.../encryption/EncryptedCacheCreateTest.java | 164 ++++
.../encryption/EncryptedCacheDestroyTest.java | 127 +++
.../EncryptedCacheGroupCreateTest.java | 116 +++
.../encryption/EncryptedCacheNodeJoinTest.java | 237 +++++
.../EncryptedCachePreconfiguredRestartTest.java | 87 ++
.../encryption/EncryptedCacheRestartTest.java | 64 ++
.../pagemem/impl/PageMemoryNoLoadSelfTest.java | 18 +-
...gnitePdsRecoveryAfterFileCorruptionTest.java | 8 +-
...ckpointSimulationWithRealCpDisabledTest.java | 21 +-
.../db/file/IgnitePdsPageReplacementTest.java | 2 +-
.../persistence/db/wal/WalCompactionTest.java | 12 +-
.../pagemem/BPlusTreePageMemoryImplTest.java | 22 +-
.../BPlusTreeReuseListPageMemoryImplTest.java | 18 +-
...gnitePageMemReplaceDelayedWriteUnitTest.java | 7 +-
.../pagemem/IndexStoragePageMemoryImplTest.java | 22 +-
.../pagemem/PageMemoryImplNoLoadTest.java | 22 +-
.../persistence/pagemem/PageMemoryImplTest.java | 7 +
.../wal/memtracker/PageMemoryTracker.java | 13 +
.../KeystoreEncryptionSpiSelfTest.java | 123 +++
.../ignite/testframework/GridTestUtils.java | 81 +-
.../testframework/junits/GridAbstractTest.java | 4 +-
.../IgniteBasicWithPersistenceTestSuite.java | 15 +
.../testsuites/IgniteKernalSelfTestSuite.java | 1 -
.../ignite/testsuites/IgniteSpiTestSuite.java | 3 +
.../src/test/resources/other_tde_keystore.jks | Bin 0 -> 347 bytes
modules/core/src/test/resources/tde.jks | Bin 0 -> 347 bytes
.../query/h2/ddl/DdlStatementsProcessor.java | 3 +-
.../query/h2/sql/GridSqlCreateTable.java | 17 +
.../query/h2/sql/GridSqlQueryParser.java | 8 +
.../cache/encryption/EncryptedSqlTableTest.java | 69 ++
.../cache/index/H2DynamicTableSelfTest.java | 4 +-
.../IgniteCacheQuerySelfTestSuite.java | 2 +
modules/indexing/src/test/resources/tde.jks | Bin 0 -> 347 bytes
.../Apache.Ignite.Core.Tests.DotNetCore/tde.jks | Bin 0 -> 347 bytes
.../ApiParity/IgniteConfigurationParityTest.cs | 5 +-
.../IgniteConfigurationTest.cs | 17 +
.../Apache.Ignite.Core.csproj | 6 +-
.../Cache/Configuration/CacheConfiguration.cs | 13 +
.../Encryption/IEncryptionSpi.cs | 34 +
.../Keystore/KeystoreEncryptionSpi.cs | 84 ++
.../Encryption/Keystore/Package-Info.cs | 26 +
.../Encryption/Package-Info.cs | 26 +
.../Apache.Ignite.Core/IgniteConfiguration.cs | 31 +
.../IgniteConfigurationSection.xsd | 39 +-
.../spring/src/test/config/enc/base-enc-cfg.xml | 70 ++
.../src/test/config/enc/enc-cache-client.xml | 35 +
.../spring/src/test/config/enc/enc-cache.xml | 35 +
.../spring/src/test/config/enc/enc-group-2.xml | 36 +
.../spring/src/test/config/enc/enc-group.xml | 37 +
.../config/enc/not-encrypted-cache-in-group.xml | 36 +
.../src/test/config/enc/not-encrypted-cache.xml | 35 +
.../SpringEncryptedCacheRestartClientTest.java | 60 ++
.../SpringEncryptedCacheRestartTest.java | 190 ++++
.../testsuites/IgniteSpringTestSuite.java | 6 +
modules/spring/src/test/resources/tde.jks | Bin 0 -> 347 bytes
.../config/benchmark-multicast-tde.properties | 128 +++
modules/yardstick/config/ignite-base-config.xml | 18 +-
modules/yardstick/config/ignite-tde-config.xml | 55 ++
modules/yardstick/src/main/resources/tde.jks | Bin 0 -> 347 bytes
145 files changed, 6319 insertions(+), 320 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/encryption/JmhKeystoreEncryptionSpiBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/encryption/JmhKeystoreEncryptionSpiBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/encryption/JmhKeystoreEncryptionSpiBenchmark.java
new file mode 100644
index 0000000..932d57e
--- /dev/null
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/encryption/JmhKeystoreEncryptionSpiBenchmark.java
@@ -0,0 +1,117 @@
+/*
+ * 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.ignite.internal.benchmarks.jmh.encryption;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.internal.benchmarks.jmh.JmhAbstractBenchmark;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import static org.apache.ignite.internal.util.IgniteUtils.resolveIgnitePath;
+
+/**
+ */
+public class JmhKeystoreEncryptionSpiBenchmark extends JmhAbstractBenchmark {
+ /** Data amount. */
+ private static final int DATA_AMOUNT = 100;
+
+ public static final int PAGE_SIZE = 1024 * 4;
+
+ /** */
+ @Benchmark
+ public void encryptBenchmark(EncryptionData d, Blackhole receiver) {
+ for (int i = 0; i < DATA_AMOUNT; i++) {
+ ByteBuffer[] dt = d.randomData[i];
+
+ KeystoreEncryptionKey key = d.keys[ThreadLocalRandom.current().nextInt(4)];
+
+ d.encSpi.encryptNoPadding(dt[0], key, dt[1]);
+
+ receiver.consume(d.res);
+
+ dt[0].rewind();
+ dt[1].rewind();
+
+ d.encSpi.decryptNoPadding(dt[1], key, dt[0]);
+ }
+ }
+
+ @State(Scope.Thread)
+ public static class EncryptionData {
+ KeystoreEncryptionSpi encSpi;
+
+ KeystoreEncryptionKey[] keys = new KeystoreEncryptionKey[4];
+
+ ByteBuffer[][] randomData = new ByteBuffer[DATA_AMOUNT][2];
+
+ ByteBuffer res = ByteBuffer.allocate(PAGE_SIZE);
+
+ public EncryptionData() {
+ encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.setKeyStorePath(resolveIgnitePath("modules/core/src/test/resources/tde.jks").getAbsolutePath());
+ encSpi.setKeyStorePassword("love_sex_god".toCharArray());
+
+ encSpi.onBeforeStart();
+ encSpi.spiStart("test-instance");
+ }
+
+ @Setup(Level.Invocation)
+ public void prepareCollection() {
+ for (int i = 0; i < keys.length; i++)
+ keys[i] = encSpi.create();
+
+ for (int i = 0; i < DATA_AMOUNT; i++) {
+ byte[] dt = new byte[PAGE_SIZE - 16];
+
+ ThreadLocalRandom.current().nextBytes(dt);
+
+ randomData[i][0] = ByteBuffer.wrap(dt);
+ randomData[i][1] = ByteBuffer.allocate(PAGE_SIZE);
+ }
+ }
+
+ @TearDown(Level.Iteration)
+ public void tearDown() {
+ //No - op
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Options opt = new OptionsBuilder()
+ .include(JmhKeystoreEncryptionSpiBenchmark.class.getSimpleName())
+ .threads(1)
+ .forks(1)
+ .warmupIterations(10)
+ .measurementIterations(20)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
index 2f7e6c0..2599d7a 100644
--- a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
+++ b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
@@ -240,6 +240,8 @@ public class MessageCodeGenerator {
// gen.generateAndWrite(GridH2DmlResponse.class);
// gen.generateAndWrite(GridNearTxEnlistRequest.class);
// gen.generateAndWrite(GridNearTxEnlistResponse.class);
+// gen.generateAndWrite(GenerateEncryptionKeyRequest.class);
+// gen.generateAndWrite(GenerateEncryptionKeyResponse.class);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index fb3789d..795fcfd 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -50,7 +50,9 @@ import org.apache.ignite.cache.query.annotations.QuerySqlFunction;
import org.apache.ignite.cache.store.CacheStore;
import org.apache.ignite.cache.store.CacheStoreSessionListener;
import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.internal.binary.BinaryContext;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
import org.apache.ignite.internal.processors.query.QueryUtils;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.A;
@@ -373,6 +375,15 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
/** Events disabled. */
private boolean evtsDisabled = DFLT_EVENTS_DISABLED;
+ /**
+ * Flag indicating whether data must be encrypted.
+ * If {@code true} data on the disk will be encrypted.
+ *
+ * @see EncryptionSpi
+ * @see KeystoreEncryptionSpi
+ */
+ private boolean encryptionEnabled;
+
/** Empty constructor (all values are initialized to their defaults). */
public CacheConfiguration() {
/* No-op. */
@@ -412,6 +423,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
cpOnRead = cc.isCopyOnRead();
dfltLockTimeout = cc.getDefaultLockTimeout();
eagerTtl = cc.isEagerTtl();
+ encryptionEnabled = cc.isEncryptionEnabled();
evictFilter = cc.getEvictionFilter();
evictPlc = cc.getEvictionPolicy();
evictPlcFactory = cc.getEvictionPolicyFactory();
@@ -2268,6 +2280,27 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
return this;
}
+ /**
+ * Gets flag indicating whether data must be encrypted.
+ *
+ * @return {@code True} if this cache persistent data is encrypted.
+ */
+ public boolean isEncryptionEnabled() {
+ return encryptionEnabled;
+ }
+
+ /**
+ * Sets encrypted flag.
+ *
+ * @param encryptionEnabled {@code True} if this cache persistent data should be encrypted.
+ * @return {@code this} for chaining.
+ */
+ public CacheConfiguration<K, V> setEncryptionEnabled(boolean encryptionEnabled) {
+ this.encryptionEnabled = encryptionEnabled;
+
+ return this;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(CacheConfiguration.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 964c73b..1dbec7d 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -40,6 +40,7 @@ import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.compute.ComputeJob;
import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.events.Event;
import org.apache.ignite.events.EventType;
import org.apache.ignite.failure.FailureHandler;
@@ -367,6 +368,9 @@ public class IgniteConfiguration {
/** Address resolver. */
private AddressResolver addrRslvr;
+ /** Encryption SPI. */
+ private EncryptionSpi encryptionSpi;
+
/** Cache configurations. */
private CacheConfiguration[] cacheCfg;
@@ -537,6 +541,7 @@ public class IgniteConfiguration {
failSpi = cfg.getFailoverSpi();
loadBalancingSpi = cfg.getLoadBalancingSpi();
indexingSpi = cfg.getIndexingSpi();
+ encryptionSpi = cfg.getEncryptionSpi();
commFailureRslvr = cfg.getCommunicationFailureResolver();
@@ -2062,6 +2067,28 @@ public class IgniteConfiguration {
}
/**
+ * Sets fully configured instances of {@link EncryptionSpi}.
+ *
+ * @param encryptionSpi Fully configured instance of {@link EncryptionSpi}.
+ * @see IgniteConfiguration#getEncryptionSpi()
+ * @return {@code this} for chaining.
+ */
+ public IgniteConfiguration setEncryptionSpi(EncryptionSpi encryptionSpi) {
+ this.encryptionSpi = encryptionSpi;
+
+ return this;
+ }
+
+ /**
+ * Gets fully configured encryption SPI implementations.
+ *
+ * @return Encryption SPI implementation.
+ */
+ public EncryptionSpi getEncryptionSpi() {
+ return encryptionSpi;
+ }
+
+ /**
* Gets address resolver for addresses mapping determination.
*
* @return Address resolver.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java b/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
index 0cf3a6e..607217e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridComponent.java
@@ -67,7 +67,10 @@ public interface GridComponent {
AUTH_PROC,
/** */
- CACHE_CRD_PROC
+ CACHE_CRD_PROC,
+
+ /** Encryption manager. */
+ ENCRYPTION_MGR
}
/**
@@ -153,7 +156,7 @@ public interface GridComponent {
@Nullable public IgniteNodeValidationResult validateNode(ClusterNode node);
/** */
- @Nullable public IgniteNodeValidationResult validateNode(ClusterNode node, DiscoveryDataBag.JoiningNodeDiscoveryData discoData);
+ @Nullable public IgniteNodeValidationResult validateNode(ClusterNode node, JoiningNodeDiscoveryData discoData);
/**
* Gets unique component type to distinguish components providing discovery data. Must return non-null value
@@ -180,4 +183,4 @@ public interface GridComponent {
* @return Future to wait before completing reconnect future.
*/
@Nullable public IgniteInternalFuture<?> onReconnected(boolean clusterRestarted) throws IgniteCheckedException;
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index 4cb68da..970b8e7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -28,6 +28,7 @@ import org.apache.ignite.internal.managers.collision.GridCollisionManager;
import org.apache.ignite.internal.managers.communication.GridIoManager;
import org.apache.ignite.internal.managers.deployment.GridDeploymentManager;
import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager;
import org.apache.ignite.internal.managers.failover.GridFailoverManager;
import org.apache.ignite.internal.managers.indexing.GridIndexingManager;
@@ -425,6 +426,13 @@ public interface GridKernalContext extends Iterable<GridComponent> {
public GridIndexingManager indexing();
/**
+ * Gets encryption manager.
+ *
+ * @return Encryption manager.
+ */
+ public GridEncryptionManager encryption();
+
+ /**
* Gets workers registry.
*
* @return Workers registry.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index a0e3f93..f23e650 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -38,6 +38,7 @@ import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.failure.FailureType;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.managers.checkpoint.GridCheckpointManager;
import org.apache.ignite.internal.managers.collision.GridCollisionManager;
import org.apache.ignite.internal.managers.communication.GridIoManager;
@@ -162,6 +163,10 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
@GridToStringExclude
private GridIndexingManager indexingMgr;
+ /** */
+ @GridToStringExclude
+ private GridEncryptionManager encryptionMgr;
+
/*
* Processors.
* ==========
@@ -557,6 +562,8 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
loadMgr = (GridLoadBalancerManager)comp;
else if (comp instanceof GridIndexingManager)
indexingMgr = (GridIndexingManager)comp;
+ else if (comp instanceof GridEncryptionManager)
+ encryptionMgr = (GridEncryptionManager)comp;
/*
* Processors.
@@ -802,6 +809,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
}
/** {@inheritDoc} */
+ @Override public GridEncryptionManager encryption() {
+ return encryptionMgr;
+ }
+
+ /** {@inheritDoc} */
@Override public WorkersRegistry workersRegistry() {
return workersRegistry;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java b/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
index 98a4d8d..95d7717 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridTopic.java
@@ -133,7 +133,10 @@ public enum GridTopic {
TOPIC_EXCHANGE,
/** */
- TOPIC_CACHE_COORDINATOR;
+ TOPIC_CACHE_COORDINATOR,
+
+ /** */
+ TOPIC_GEN_ENC_KEY;
/** Enum values. */
private static final GridTopic[] VALS = values();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 32e5dd8..cfde78f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -101,6 +101,7 @@ import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.binary.BinaryUtils;
import org.apache.ignite.internal.cluster.ClusterGroupAdapter;
import org.apache.ignite.internal.cluster.IgniteClusterEx;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.managers.GridManager;
import org.apache.ignite.internal.managers.checkpoint.GridCheckpointManager;
import org.apache.ignite.internal.managers.collision.GridCollisionManager;
@@ -987,6 +988,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
startManager(new GridFailoverManager(ctx));
startManager(new GridCollisionManager(ctx));
startManager(new GridIndexingManager(ctx));
+ startManager(new GridEncryptionManager(ctx));
ackSecurity();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
index 5b764e4..4ca4f1b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
@@ -196,6 +196,9 @@ public final class IgniteNodeAttributes {
/** User authentication enabled flag. */
public static final String ATTR_AUTHENTICATION_ENABLED = ATTR_PREFIX + ".authentication.enabled";
+ /** Encryption master key digest. */
+ public static final String ATTR_ENCRYPTION_MASTER_KEY_DIGEST = ATTR_PREFIX + ".master.key.digest";
+
/** Rebalance thread pool size. */
public static final String ATTR_REBALANCE_POOL_SIZE = ATTR_PREFIX + ".rebalance.pool.size";
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
index ed0fbe9..95001de 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
@@ -115,6 +115,7 @@ import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
import org.apache.ignite.spi.deployment.local.LocalDeploymentSpi;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.spi.eventstorage.NoopEventStorageSpi;
import org.apache.ignite.spi.failover.always.AlwaysFailoverSpi;
import org.apache.ignite.spi.indexing.noop.NoopIndexingSpi;
@@ -2444,6 +2445,9 @@ public class IgnitionEx {
if (cfg.getIndexingSpi() == null)
cfg.setIndexingSpi(new NoopIndexingSpi());
+
+ if (cfg.getEncryptionSpi() == null)
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 54efb47..e405d7d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -46,6 +46,8 @@ import org.apache.ignite.internal.processors.cache.CacheEvictionEntry;
import org.apache.ignite.internal.processors.cache.CacheInvokeDirectResult;
import org.apache.ignite.internal.processors.cache.CacheObjectByteArrayImpl;
import org.apache.ignite.internal.processors.cache.CacheObjectImpl;
+import org.apache.ignite.internal.managers.encryption.GenerateEncryptionKeyRequest;
+import org.apache.ignite.internal.managers.encryption.GenerateEncryptionKeyResponse;
import org.apache.ignite.internal.processors.cache.GridCacheEntryInfo;
import org.apache.ignite.internal.processors.cache.GridCacheMvccEntryInfo;
import org.apache.ignite.internal.processors.cache.GridCacheReturn;
@@ -1084,6 +1086,16 @@ public class GridIoMessageFactory implements MessageFactory {
break;
+ case 162:
+ msg = new GenerateEncryptionKeyRequest();
+
+ break;
+
+ case 163:
+ msg = new GenerateEncryptionKeyResponse();
+
+ break;
+
// [-3..119] [124..129] [-23..-27] [-36..-55]- this
// [120..123] - DR
// [-4..-22, -30..-35] - SQL
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
index 19c11ac..d7514a0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
@@ -795,6 +795,8 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
ctx.cache().context().exchange().onLocalJoin(discoEvt, discoCache);
ctx.authentication().onLocalJoin();
+
+ ctx.encryption().onLocalJoin();
}
IgniteInternalFuture<Boolean> transitionWaitFut = ctx.state().onLocalJoin(discoCache);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyRequest.java
new file mode 100644
index 0000000..3d48014
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyRequest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.ignite.internal.managers.encryption;
+
+import java.nio.ByteBuffer;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Generate encryption key request.
+ */
+public class GenerateEncryptionKeyRequest implements Message {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Request ID. */
+ private IgniteUuid id = IgniteUuid.randomUuid();
+
+ /** */
+ private int keyCnt;
+
+ /** */
+ public GenerateEncryptionKeyRequest() {
+ }
+
+ /**
+ * @param keyCnt Count of encryption key to generate.
+ */
+ public GenerateEncryptionKeyRequest(int keyCnt) {
+ this.keyCnt = keyCnt;
+ }
+
+ /**
+ * @return Request id.
+ */
+ public IgniteUuid id() {
+ return id;
+ }
+
+ /**
+ * @return Count of encryption key to generate.
+ */
+ public int keyCount() {
+ return keyCnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeIgniteUuid("id", id))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeInt("keyCnt", keyCnt))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ id = reader.readIgniteUuid("id");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ keyCnt = reader.readInt("keyCnt");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GenerateEncryptionKeyRequest.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public short directType() {
+ return 162;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GenerateEncryptionKeyRequest.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyResponse.java
new file mode 100644
index 0000000..8971248
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GenerateEncryptionKeyResponse.java
@@ -0,0 +1,148 @@
+/*
+ * 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.ignite.internal.managers.encryption;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Generate encryption key response.
+ */
+public class GenerateEncryptionKeyResponse implements Message {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Request message ID. */
+ private IgniteUuid id;
+
+ /** */
+ @GridDirectCollection(byte[].class)
+ private Collection<byte[]> encKeys;
+
+ /** */
+ public GenerateEncryptionKeyResponse() {
+ }
+
+ /**
+ * @param id Request id.
+ * @param encKeys Encryption keys.
+ */
+ public GenerateEncryptionKeyResponse(IgniteUuid id, Collection<byte[]> encKeys) {
+ this.id = id;
+ this.encKeys = encKeys;
+ }
+
+ /**
+ * @return Request id.
+ */
+ public IgniteUuid requestId() {
+ return id;
+ }
+
+ /**
+ * @return Encryption keys.
+ */
+ public Collection<byte[]> encryptionKeys() {
+ return encKeys;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeCollection("encKeys", encKeys, MessageCollectionItemType.BYTE_ARR))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeIgniteUuid("id", id))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ encKeys = reader.readCollection("encKeys", MessageCollectionItemType.BYTE_ARR);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ id = reader.readIgniteUuid("id");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GenerateEncryptionKeyResponse.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public short directType() {
+ return 163;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ //No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GenerateEncryptionKeyResponse.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GridEncryptionManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GridEncryptionManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GridEncryptionManager.java
new file mode 100644
index 0000000..a1c0fdc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/encryption/GridEncryptionManager.java
@@ -0,0 +1,864 @@
+/*
+ * 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.ignite.internal.managers.encryption;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.managers.GridManagerAdapter;
+import org.apache.ignite.internal.managers.communication.GridMessageListener;
+import org.apache.ignite.internal.managers.eventstorage.DiscoveryEventListener;
+import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor;
+import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
+import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetastorageLifecycleListener;
+import org.apache.ignite.internal.processors.cache.persistence.metastorage.ReadOnlyMetastorage;
+import org.apache.ignite.internal.processors.cache.persistence.metastorage.ReadWriteMetastorage;
+import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport;
+import org.apache.ignite.internal.util.future.GridFinishedFuture;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.apache.ignite.internal.util.lang.GridPlainClosure;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteFutureCancelledException;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.lang.IgniteProductVersion;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.spi.IgniteNodeValidationResult;
+import org.apache.ignite.spi.discovery.DiscoveryDataBag;
+import org.apache.ignite.spi.discovery.DiscoveryDataBag.GridDiscoveryData;
+import org.apache.ignite.spi.discovery.DiscoveryDataBag.JoiningNodeDiscoveryData;
+import org.apache.ignite.spi.discovery.DiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.events.EventType.EVT_NODE_FAILED;
+import static org.apache.ignite.events.EventType.EVT_NODE_LEFT;
+import static org.apache.ignite.internal.GridComponent.DiscoveryDataExchangeType.ENCRYPTION_MGR;
+import static org.apache.ignite.internal.GridTopic.TOPIC_GEN_ENC_KEY;
+import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_ENCRYPTION_MASTER_KEY_DIGEST;
+import static org.apache.ignite.internal.managers.communication.GridIoPolicy.SYSTEM_POOL;
+
+/**
+ * Manages cache keys and {@code EncryptionSpi} instances.
+ *
+ * NOTE: Following protocol applied to statically configured caches.
+ * For dynamically created caches key generated in request creation.
+ *
+ * Group keys generation protocol:
+ *
+ * <ul>
+ * <li>Joining node:
+ * <ul>
+ * <li>1. Collects and send all stored group keys to coordinator.</li>
+ * <li>2. Generate(but doesn't store locally!) and send keys for all statically configured groups in case the not presented in metastore.</li>
+ * <li>3. Store all keys received from coordinator to local store.</li>
+ * </ul>
+ * </li>
+ * <li>Coordinator:
+ * <ul>
+ * <li>1. Checks master key digest are equal to local. If not join is rejected.</li>
+ * <li>2. Checks all stored keys from joining node are equal to stored keys. If not join is rejected.</li>
+ * <li>3. Collects all stored keys and sends it to joining node.</li>
+ * </ul>
+ * </li>
+ * <li>All nodes:
+ * <ul>
+ * <li>1. If new key for group doesn't exists locally it added to local store.</li>
+ * <li>2. If new key for group exists locally, then received key skipped.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @see GridCacheProcessor#generateEncryptionKeysAndStartCacheAfter(int, GridPlainClosure)
+ */
+public class GridEncryptionManager extends GridManagerAdapter<EncryptionSpi> implements MetastorageLifecycleListener,
+ IgniteChangeGlobalStateSupport {
+ /**
+ * Cache encryption introduced in this Ignite version.
+ */
+ private static final IgniteProductVersion CACHE_ENCRYPTION_SINCE = IgniteProductVersion.fromString("2.7.0");
+
+ /** Synchronization mutex. */
+ private final Object metaStorageMux = new Object();
+
+ /** Synchronization mutex for an generate encryption keys operations. */
+ private final Object genEcnKeyMux = new Object();
+
+ /** Disconnected flag. */
+ private volatile boolean disconnected;
+
+ /** Stopped flag. */
+ private volatile boolean stopped;
+
+ /** Flag to enable/disable write to metastore on cluster state change. */
+ private volatile boolean writeToMetaStoreEnabled;
+
+ /** Prefix for a encryption group key in meta store. */
+ public static final String ENCRYPTION_KEY_PREFIX = "grp-encryption-key-";
+
+ /** Encryption key predicate for meta store. */
+ private static final IgnitePredicate<String> ENCRYPTION_KEY_PREFIX_PRED =
+ (IgnitePredicate<String>)key -> key.startsWith(ENCRYPTION_KEY_PREFIX);
+
+ /** Group encryption keys. */
+ private Map<Integer, Serializable> grpEncKeys = new HashMap<>();
+
+ /** Pending generate encryption key futures. */
+ private ConcurrentMap<IgniteUuid, GenerateEncryptionKeyFuture> genEncKeyFuts = new ConcurrentHashMap<>();
+
+ /** Metastorage. */
+ private volatile ReadWriteMetastorage metaStorage;
+
+ /** I/O message listener. */
+ private GridMessageListener ioLsnr;
+
+ /** System discovery message listener. */
+ private DiscoveryEventListener discoLsnr;
+
+ /**
+ * @param ctx Kernel context.
+ */
+ public GridEncryptionManager(GridKernalContext ctx) {
+ super(ctx, ctx.config().getEncryptionSpi());
+
+ ctx.internalSubscriptionProcessor().registerMetastorageListener(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteCheckedException {
+ startSpi();
+
+ if (getSpi().masterKeyDigest() != null)
+ ctx.addNodeAttribute(ATTR_ENCRYPTION_MASTER_KEY_DIGEST, getSpi().masterKeyDigest());
+
+ ctx.event().addDiscoveryEventListener(discoLsnr = (evt, discoCache) -> {
+ UUID leftNodeId = evt.eventNode().id();
+
+ synchronized (genEcnKeyMux) {
+ Iterator<Map.Entry<IgniteUuid, GenerateEncryptionKeyFuture>> futsIter =
+ genEncKeyFuts.entrySet().iterator();
+
+ while (futsIter.hasNext()) {
+ GenerateEncryptionKeyFuture fut = futsIter.next().getValue();
+
+ if (!F.eq(leftNodeId, fut.nodeId()))
+ return;
+
+ try {
+ futsIter.remove();
+
+ sendGenerateEncryptionKeyRequest(fut);
+
+ genEncKeyFuts.put(fut.id(), fut);
+ }
+ catch (IgniteCheckedException e) {
+ fut.onDone(null, e);
+ }
+ }
+ }
+ }, EVT_NODE_LEFT, EVT_NODE_FAILED);
+
+ ctx.io().addMessageListener(TOPIC_GEN_ENC_KEY, ioLsnr = (nodeId, msg, plc) -> {
+ synchronized (genEcnKeyMux) {
+ if (msg instanceof GenerateEncryptionKeyRequest) {
+ GenerateEncryptionKeyRequest req = (GenerateEncryptionKeyRequest)msg;
+
+ assert req.keyCount() != 0;
+
+ List<byte[]> encKeys = new ArrayList<>(req.keyCount());
+
+ for (int i = 0; i < req.keyCount(); i++)
+ encKeys.add(getSpi().encryptKey(getSpi().create()));
+
+ try {
+ ctx.io().sendToGridTopic(nodeId, TOPIC_GEN_ENC_KEY,
+ new GenerateEncryptionKeyResponse(req.id(), encKeys), SYSTEM_POOL);
+ }
+ catch (IgniteCheckedException e) {
+ U.error(log, "Unable to send generate key response[nodeId=" + nodeId + "]");
+ }
+ }
+ else {
+ GenerateEncryptionKeyResponse resp = (GenerateEncryptionKeyResponse)msg;
+
+ GenerateEncryptionKeyFuture fut = genEncKeyFuts.get(resp.requestId());
+
+ if (fut != null)
+ fut.onDone(resp.encryptionKeys(), null);
+ else
+ U.warn(log, "Response received for a unknown request.[reqId=" + resp.requestId() + "]");
+ }
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop(boolean cancel) throws IgniteCheckedException {
+ stopSpi();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void onKernalStart0() throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void onKernalStop0(boolean cancel) {
+ synchronized (genEcnKeyMux) {
+ stopped = true;
+
+ if (ioLsnr != null)
+ ctx.io().removeMessageListener(TOPIC_GEN_ENC_KEY, ioLsnr);
+
+ if (discoLsnr != null)
+ ctx.event().removeDiscoveryEventListener(discoLsnr, EVT_NODE_LEFT, EVT_NODE_FAILED);
+
+ cancelFutures("Kernal stopped.");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onDisconnected(IgniteFuture<?> reconnectFut) {
+ synchronized (genEcnKeyMux) {
+ assert !disconnected;
+
+ disconnected = true;
+
+ cancelFutures("Client node was disconnected from topology (operation result is unknown).");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteInternalFuture<?> onReconnected(boolean clusterRestarted) {
+ synchronized (genEcnKeyMux) {
+ assert disconnected;
+
+ disconnected = false;
+
+ return null;
+ }
+ }
+
+ /**
+ * Callback for local join.
+ */
+ public void onLocalJoin() {
+ if (notCoordinator())
+ return;
+
+ //We can't store keys before node join to cluster(on statically configured cache registration).
+ //Because, keys should be received from cluster.
+ //Otherwise, we would generate different keys on each started node.
+ //So, after starting, coordinator saves locally newly generated encryption keys.
+ //And sends that keys to every joining node.
+ synchronized (metaStorageMux) {
+ //Keys read from meta storage.
+ HashMap<Integer, byte[]> knownEncKeys = knownEncryptionKeys();
+
+ //Generated(not saved!) keys for a new caches.
+ //Configured statically in config, but doesn't stored on the disk.
+ HashMap<Integer, byte[]> newEncKeys =
+ newEncryptionKeys(knownEncKeys == null ? Collections.EMPTY_SET : knownEncKeys.keySet());
+
+ if (newEncKeys == null)
+ return;
+
+ //We can store keys to the disk, because we are on a coordinator.
+ for (Map.Entry<Integer, byte[]> entry : newEncKeys.entrySet()) {
+ groupKey(entry.getKey(), entry.getValue());
+
+ U.quietAndInfo(log, "Added encryption key on local join [grpId=" + entry.getKey() + "]");
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public IgniteNodeValidationResult validateNode(ClusterNode node,
+ JoiningNodeDiscoveryData discoData) {
+ IgniteNodeValidationResult res = super.validateNode(node, discoData);
+
+ if (res != null)
+ return res;
+
+ if (node.isClient())
+ return null;
+
+ res = validateNode(node);
+
+ if (res != null)
+ return res;
+
+ if (!discoData.hasJoiningNodeData()) {
+ U.quietAndInfo(log, "Joining node doesn't have encryption data [node=" + node.id() + "]");
+
+ return null;
+ }
+
+ NodeEncryptionKeys nodeEncKeys = (NodeEncryptionKeys)discoData.joiningNodeData();
+
+ if (nodeEncKeys == null || F.isEmpty(nodeEncKeys.knownKeys)) {
+ U.quietAndInfo(log, "Joining node doesn't have stored group keys [node=" + node.id() + "]");
+
+ return null;
+ }
+
+ for (Map.Entry<Integer, byte[]> entry : nodeEncKeys.knownKeys.entrySet()) {
+ Serializable locEncKey = grpEncKeys.get(entry.getKey());
+
+ if (locEncKey == null)
+ continue;
+
+ Serializable rmtKey = getSpi().decryptKey(entry.getValue());
+
+ if (F.eq(locEncKey, rmtKey))
+ continue;
+
+ return new IgniteNodeValidationResult(ctx.localNodeId(),
+ "Cache key differs! Node join is rejected. [node=" + node.id() + ", grp=" + entry.getKey() + "]",
+ "Cache key differs! Node join is rejected.");
+ }
+
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public IgniteNodeValidationResult validateNode(ClusterNode node) {
+ IgniteNodeValidationResult res = super.validateNode(node);
+
+ if (res != null)
+ return res;
+
+ if (node.isClient())
+ return null;
+
+ byte[] lclMkDig = getSpi().masterKeyDigest();
+
+ byte[] rmtMkDig = node.attribute(ATTR_ENCRYPTION_MASTER_KEY_DIGEST);
+
+ if (Arrays.equals(lclMkDig, rmtMkDig))
+ return null;
+
+ return new IgniteNodeValidationResult(ctx.localNodeId(),
+ "Master key digest differs! Node join is rejected. [node=" + node.id() + "]",
+ "Master key digest differs! Node join is rejected.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void collectJoiningNodeData(DiscoveryDataBag dataBag) {
+ HashMap<Integer, byte[]> knownEncKeys = knownEncryptionKeys();
+
+ HashMap<Integer, byte[]> newKeys =
+ newEncryptionKeys(knownEncKeys == null ? Collections.EMPTY_SET : knownEncKeys.keySet());
+
+ if ((knownEncKeys == null && newKeys == null) || dataBag.isJoiningNodeClient())
+ return;
+
+ if (log.isInfoEnabled()) {
+ String knownGrps = F.isEmpty(knownEncKeys) ? null : F.concat(knownEncKeys.keySet(), ",");
+
+ if (knownGrps != null)
+ U.quietAndInfo(log, "Sending stored group keys to coordinator [grps=" + knownGrps + "]");
+
+ String newGrps = F.isEmpty(newKeys) ? null : F.concat(newKeys.keySet(), ",");
+
+ if (newGrps != null)
+ U.quietAndInfo(log, "Sending new group keys to coordinator [grps=" + newGrps + "]");
+ }
+
+ dataBag.addJoiningNodeData(ENCRYPTION_MGR.ordinal(), new NodeEncryptionKeys(knownEncKeys, newKeys));
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onJoiningNodeDataReceived(JoiningNodeDiscoveryData data) {
+ NodeEncryptionKeys nodeEncryptionKeys = (NodeEncryptionKeys)data.joiningNodeData();
+
+ if (nodeEncryptionKeys == null || nodeEncryptionKeys.newKeys == null || ctx.clientNode())
+ return;
+
+ for (Map.Entry<Integer, byte[]> entry : nodeEncryptionKeys.newKeys.entrySet()) {
+ if (groupKey(entry.getKey()) == null) {
+ U.quietAndInfo(log, "Store group key received from joining node [node=" +
+ data.joiningNodeId() + ", grp=" + entry.getKey() + "]");
+
+ groupKey(entry.getKey(), entry.getValue());
+ }
+ else {
+ U.quietAndInfo(log, "Skip group key received from joining node. Already exists. [node=" +
+ data.joiningNodeId() + ", grp=" + entry.getKey() + "]");
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void collectGridNodeData(DiscoveryDataBag dataBag) {
+ if (dataBag.isJoiningNodeClient() || dataBag.commonDataCollectedFor(ENCRYPTION_MGR.ordinal()))
+ return;
+
+ HashMap<Integer, byte[]> knownEncKeys = knownEncryptionKeys();
+
+ HashMap<Integer, byte[]> newKeys =
+ newEncryptionKeys(knownEncKeys == null ? Collections.EMPTY_SET : knownEncKeys.keySet());
+
+ if (knownEncKeys == null)
+ knownEncKeys = newKeys;
+ else if (newKeys != null) {
+ for (Map.Entry<Integer, byte[]> entry : newKeys.entrySet()) {
+ byte[] old = knownEncKeys.putIfAbsent(entry.getKey(), entry.getValue());
+
+ assert old == null;
+ }
+ }
+
+ dataBag.addGridCommonData(ENCRYPTION_MGR.ordinal(), knownEncKeys);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onGridDataReceived(GridDiscoveryData data) {
+ Map<Integer, byte[]> encKeysFromCluster = (Map<Integer, byte[]>)data.commonData();
+
+ if (F.isEmpty(encKeysFromCluster))
+ return;
+
+ for (Map.Entry<Integer, byte[]> entry : encKeysFromCluster.entrySet()) {
+ if (groupKey(entry.getKey()) == null) {
+ U.quietAndInfo(log, "Store group key received from coordinator [grp=" + entry.getKey() + "]");
+
+ groupKey(entry.getKey(), entry.getValue());
+ }
+ else {
+ U.quietAndInfo(log, "Skip group key received from coordinator. Already exists. [grp=" +
+ entry.getKey() + "]");
+ }
+ }
+ }
+
+ /**
+ * Returns group encryption key.
+ *
+ * @param grpId Group id.
+ * @return Group encryption key.
+ */
+ @Nullable public Serializable groupKey(int grpId) {
+ return grpEncKeys.get(grpId);
+ }
+
+ /**
+ * Store group encryption key.
+ *
+ * @param grpId Group id.
+ * @param encGrpKey Encrypted group key.
+ */
+ public void groupKey(int grpId, byte[] encGrpKey) {
+ assert !grpEncKeys.containsKey(grpId);
+
+ Serializable encKey = getSpi().decryptKey(encGrpKey);
+
+ synchronized (metaStorageMux) {
+ if (log.isDebugEnabled())
+ log.debug("Key added. [grp=" + grpId + "]");
+
+ grpEncKeys.put(grpId, encKey);
+
+ writeToMetaStore(grpId, encGrpKey);
+ }
+ }
+
+ /**
+ * Removes encryption key.
+ *
+ * @param grpId Group id.
+ */
+ private void removeGroupKey(int grpId) {
+ synchronized (metaStorageMux) {
+ ctx.cache().context().database().checkpointReadLock();
+
+ try {
+ grpEncKeys.remove(grpId);
+
+ metaStorage.remove(ENCRYPTION_KEY_PREFIX + grpId);
+
+ if (log.isDebugEnabled())
+ log.debug("Key removed. [grp=" + grpId + "]");
+ }
+ catch (IgniteCheckedException e) {
+ U.error(log, "Failed to clear meta storage", e);
+ }
+ finally {
+ ctx.cache().context().database().checkpointReadUnlock();
+ }
+ }
+ }
+
+ /**
+ * Callback for cache group start event.
+ * @param grpId Group id.
+ * @param encKey Encryption key
+ */
+ public void beforeCacheGroupStart(int grpId, @Nullable byte[] encKey) {
+ if (encKey == null || ctx.clientNode())
+ return;
+
+ groupKey(grpId, encKey);
+ }
+
+ /**
+ * Callback for cache group destroy event.
+ * @param grpId Group id.
+ */
+ public void onCacheGroupDestroyed(int grpId) {
+ if (groupKey(grpId) == null)
+ return;
+
+ removeGroupKey(grpId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onReadyForRead(ReadOnlyMetastorage metastorage) {
+ try {
+ Map<String, ? extends Serializable> encKeys = metastorage.readForPredicate(ENCRYPTION_KEY_PREFIX_PRED);
+
+ if (encKeys.isEmpty())
+ return;
+
+ for (String key : encKeys.keySet()) {
+ Integer grpId = Integer.valueOf(key.replace(ENCRYPTION_KEY_PREFIX, ""));
+
+ byte[] encGrpKey = (byte[])encKeys.get(key);
+
+ grpEncKeys.putIfAbsent(grpId, getSpi().decryptKey(encGrpKey));
+ }
+
+ if (!grpEncKeys.isEmpty()) {
+ U.quietAndInfo(log, "Encryption keys loaded from metastore. [grps=" +
+ F.concat(grpEncKeys.keySet(), ",") + "]");
+ }
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException("Failed to read encryption keys state.", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onReadyForReadWrite(ReadWriteMetastorage metaStorage) throws IgniteCheckedException {
+ synchronized (metaStorageMux) {
+ this.metaStorage = metaStorage;
+
+ writeToMetaStoreEnabled = true;
+
+ writeAllToMetaStore();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onActivate(GridKernalContext kctx) throws IgniteCheckedException {
+ synchronized (metaStorageMux) {
+ writeToMetaStoreEnabled = metaStorage != null;
+
+ if (writeToMetaStoreEnabled)
+ writeAllToMetaStore();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onDeActivate(GridKernalContext kctx) {
+ synchronized (metaStorageMux) {
+ writeToMetaStoreEnabled = false;
+ }
+ }
+
+ /**
+ * @param keyCnt Count of keys to generate.
+ * @return Future that will contain results of generation.
+ */
+ public IgniteInternalFuture<Collection<byte[]>> generateKeys(int keyCnt) {
+ if (keyCnt == 0 || !ctx.clientNode())
+ return new GridFinishedFuture<>(createKeys(keyCnt));
+
+ synchronized (genEcnKeyMux) {
+ if (disconnected || stopped) {
+ return new GridFinishedFuture<>(
+ new IgniteFutureCancelledException("Node " + (stopped ? "stopped" : "disconnected")));
+ }
+
+ try {
+ GenerateEncryptionKeyFuture genEncKeyFut = new GenerateEncryptionKeyFuture(keyCnt);
+
+ sendGenerateEncryptionKeyRequest(genEncKeyFut);
+
+ genEncKeyFuts.put(genEncKeyFut.id(), genEncKeyFut);
+
+ return genEncKeyFut;
+ }
+ catch (IgniteCheckedException e) {
+ return new GridFinishedFuture<>(e);
+ }
+ }
+ }
+
+ /** */
+ private void sendGenerateEncryptionKeyRequest(GenerateEncryptionKeyFuture fut) throws IgniteCheckedException {
+ ClusterNode rndNode = U.randomServerNode(ctx);
+
+ if (rndNode == null)
+ throw new IgniteCheckedException("There is no node to send GenerateEncryptionKeyRequest to");
+
+ GenerateEncryptionKeyRequest req = new GenerateEncryptionKeyRequest(fut.keyCount());
+
+ fut.id(req.id());
+ fut.nodeId(rndNode.id());
+
+ ctx.io().sendToGridTopic(rndNode.id(), TOPIC_GEN_ENC_KEY, req, SYSTEM_POOL);
+ }
+
+ /**
+ * Writes all unsaved grpEncKeys to metaStorage.
+ * @throws IgniteCheckedException If failed.
+ */
+ private void writeAllToMetaStore() throws IgniteCheckedException {
+ for (Map.Entry<Integer, Serializable> entry : grpEncKeys.entrySet()) {
+ if (metaStorage.read(ENCRYPTION_KEY_PREFIX + entry.getKey()) != null)
+ continue;
+
+ writeToMetaStore(entry.getKey(), getSpi().encryptKey(entry.getValue()));
+ }
+ }
+
+ /**
+ * Checks cache encryption supported by all nodes in cluster.
+ *
+ * @throws IgniteCheckedException If check fails.
+ */
+ public void checkEncryptedCacheSupported() throws IgniteCheckedException {
+ Collection<ClusterNode> nodes = ctx.grid().cluster().nodes();
+
+ for (ClusterNode node : nodes) {
+ if (CACHE_ENCRYPTION_SINCE.compareTo(node.version()) > 0) {
+ throw new IgniteCheckedException("All nodes in cluster should be 2.7.0 or greater " +
+ "to create encrypted cache! [nodeId=" + node.id() + "]");
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public DiscoveryDataExchangeType discoveryDataType() {
+ return ENCRYPTION_MGR;
+ }
+
+ /**
+ * Writes encryption key to metastore.
+ *
+ * @param grpId Group id.
+ * @param encGrpKey Group encryption key.
+ */
+ private void writeToMetaStore(int grpId, byte[] encGrpKey) {
+ if (metaStorage == null || !writeToMetaStoreEnabled)
+ return;
+
+ ctx.cache().context().database().checkpointReadLock();
+
+ try {
+ metaStorage.write(ENCRYPTION_KEY_PREFIX + grpId, encGrpKey);
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException("Failed to write cache group encryption key [grpId=" + grpId + ']', e);
+ }
+ finally {
+ ctx.cache().context().database().checkpointReadUnlock();
+ }
+ }
+
+ /**
+ * @param knownKeys Saved keys set.
+ * @return New keys for local cache groups.
+ */
+ @Nullable private HashMap<Integer, byte[]> newEncryptionKeys(Set<Integer> knownKeys) {
+ Map<Integer, CacheGroupDescriptor> grpDescs = ctx.cache().cacheGroupDescriptors();
+
+ HashMap<Integer, byte[]> newKeys = null;
+
+ for (CacheGroupDescriptor grpDesc : grpDescs.values()) {
+ if (knownKeys.contains(grpDesc.groupId()) || !grpDesc.config().isEncryptionEnabled())
+ continue;
+
+ if (newKeys == null)
+ newKeys = new HashMap<>();
+
+ newKeys.put(grpDesc.groupId(), getSpi().encryptKey(getSpi().create()));
+ }
+
+ return newKeys;
+ }
+
+ /**
+ * @return Local encryption keys.
+ */
+ @Nullable private HashMap<Integer, byte[]> knownEncryptionKeys() {
+ if (F.isEmpty(grpEncKeys))
+ return null;
+
+ HashMap<Integer, byte[]> knownKeys = new HashMap<>();
+
+ for (Map.Entry<Integer, Serializable> entry : grpEncKeys.entrySet())
+ knownKeys.put(entry.getKey(), getSpi().encryptKey(entry.getValue()));
+
+ return knownKeys;
+ }
+
+ /**
+ * Generates required count of encryption keys.
+ *
+ * @param keyCnt Keys count.
+ * @return Collection with newly generated encryption keys.
+ */
+ private Collection<byte[]> createKeys(int keyCnt) {
+ if (keyCnt == 0)
+ return Collections.emptyList();
+
+ List<byte[]> encKeys = new ArrayList<>(keyCnt);
+
+ for(int i=0; i<keyCnt; i++)
+ encKeys.add(getSpi().encryptKey(getSpi().create()));
+
+ return encKeys;
+ }
+
+ /**
+ * @param msg Error message.
+ */
+ private void cancelFutures(String msg) {
+ for (GenerateEncryptionKeyFuture fut : genEncKeyFuts.values())
+ fut.onDone(new IgniteFutureCancelledException(msg));
+ }
+
+ /**
+ * Checks whether local node is coordinator. Nodes that are leaving or failed
+ * (but are still in topology) are removed from search.
+ *
+ * @return {@code true} if local node is coordinator.
+ */
+ private boolean notCoordinator() {
+ DiscoverySpi spi = ctx.discovery().getInjectedDiscoverySpi();
+
+ if (spi instanceof TcpDiscoverySpi)
+ return !((TcpDiscoverySpi)spi).isLocalNodeCoordinator();
+ else {
+ ClusterNode crd = null;
+
+ for (ClusterNode node : ctx.discovery().aliveServerNodes()) {
+ if (crd == null || crd.order() > node.order())
+ crd = node;
+ }
+
+ return crd == null || !F.eq(ctx.localNodeId(), crd.id());
+ }
+ }
+
+ /** */
+ public static class NodeEncryptionKeys implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ NodeEncryptionKeys(Map<Integer, byte[]> knownKeys, Map<Integer, byte[]> newKeys) {
+ this.knownKeys = knownKeys;
+ this.newKeys = newKeys;
+ }
+
+ /** Known i.e. stored in {@code ReadWriteMetastorage} keys from node. */
+ Map<Integer, byte[]> knownKeys;
+
+ /** New keys i.e. keys for a local statically configured caches. */
+ Map<Integer, byte[]> newKeys;
+ }
+
+ /** */
+ @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
+ private class GenerateEncryptionKeyFuture extends GridFutureAdapter<Collection<byte[]>> {
+ /** */
+ private IgniteUuid id;
+
+ /** */
+ private int keyCnt;
+
+ /** */
+ private UUID nodeId;
+
+ /**
+ * @param keyCnt Count of keys to generate.
+ */
+ private GenerateEncryptionKeyFuture(int keyCnt) {
+ this.keyCnt = keyCnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean onDone(@Nullable Collection<byte[]> res, @Nullable Throwable err) {
+ // Make sure to remove future before completion.
+ genEncKeyFuts.remove(id, this);
+
+ return super.onDone(res, err);
+ }
+
+ /** */
+ public IgniteUuid id() {
+ return id;
+ }
+
+ /** */
+ public void id(IgniteUuid id) {
+ this.id = id;
+ }
+
+ /** */
+ public UUID nodeId() {
+ return nodeId;
+ }
+
+ /** */
+ public void nodeId(UUID nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ /** */
+ public int keyCount() {
+ return keyCnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GenerateEncryptionKeyFuture.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageMemory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageMemory.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageMemory.java
index f7391d2..3ef0ec7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageMemory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/PageMemory.java
@@ -43,6 +43,12 @@ public interface PageMemory extends PageIdAllocator, PageSupport {
public int pageSize();
/**
+ * @param grpId Group id.
+ * @return Page size without encryption overhead.
+ */
+ public int realPageSize(int grpId);
+
+ /**
* @return Page size with system overhead, in bytes.
*/
public int systemPageSize();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
index 02afac8..66d713c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
@@ -341,6 +341,11 @@ public class PageMemoryNoStoreImpl implements PageMemory {
return sysPageSize;
}
+ /** {@inheritDoc} */
+ @Override public int realPageSize(int grpId) {
+ return pageSize();
+ }
+
/**
* @return Next index.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
index 42d584d..7a7f964 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/store/PageStore.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.pagemem.store;
import org.apache.ignite.IgniteCheckedException;
import java.nio.ByteBuffer;
+import org.apache.ignite.internal.processors.cache.persistence.StorageException;
/**
* Persistent store of pages.
@@ -101,4 +102,30 @@ public interface PageStore {
* @return Page store version.
*/
public int version();
+
+ /**
+ * @param cleanFile {@code True} to delete file.
+ * @throws StorageException If failed.
+ */
+ public void stop(boolean cleanFile) throws StorageException;
+
+ /**
+ * Starts recover process.
+ */
+ public void beginRecover();
+
+ /**
+ * Ends recover process.
+ *
+ * @throws StorageException If failed.
+ */
+ public void finishRecover() throws StorageException;
+
+ /**
+ * Truncates and deletes partition file.
+ *
+ * @param tag New partition tag.
+ * @throws StorageException If failed.
+ */
+ public void truncate(int tag) throws StorageException;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/EncryptedRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/EncryptedRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/EncryptedRecord.java
new file mode 100644
index 0000000..234292b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/EncryptedRecord.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ignite.internal.pagemem.wal.record;
+
+/**
+ * Encrypted record from WAL.
+ * That types of record returned from a {@code RecordDataSerializer} on offline WAL iteration.
+ */
+public class EncryptedRecord extends WALRecord implements WalRecordCacheGroupAware {
+ /**
+ * Group id.
+ */
+ private int grpId;
+
+ /**
+ * Type of plain record.
+ */
+ private RecordType plainRecType;
+
+ /**
+ * @param grpId Group id
+ * @param plainRecType Plain record type.
+ */
+ public EncryptedRecord(int grpId, RecordType plainRecType) {
+ this.grpId = grpId;
+ this.plainRecType = plainRecType;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RecordType type() {
+ return RecordType.ENCRYPTED_RECORD;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int groupId() {
+ return grpId;
+ }
+
+ /**
+ * @return Type of plain record.
+ */
+ public RecordType plainRecordType() {
+ return plainRecType;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/PageSnapshot.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/PageSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/PageSnapshot.java
index 1aa065e..d3a465d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/PageSnapshot.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/PageSnapshot.java
@@ -38,21 +38,30 @@ public class PageSnapshot extends WALRecord implements WalRecordCacheGroupAware{
private FullPageId fullPageId;
/**
+ * PageSIze without encryption overhead.
+ */
+ private int realPageSize;
+
+ /**
* @param fullId Full page ID.
* @param arr Read array.
+ * @param realPageSize Page size without encryption overhead.
*/
- public PageSnapshot(FullPageId fullId, byte[] arr) {
- fullPageId = fullId;
- pageData = arr;
+ public PageSnapshot(FullPageId fullId, byte[] arr, int realPageSize) {
+ this.fullPageId = fullId;
+ this.pageData = arr;
+ this.realPageSize = realPageSize;
}
/**
* @param fullPageId Full page ID.
* @param ptr Pointer to copy from.
* @param pageSize Page size.
+ * @param realPageSize Page size without encryption overhead.
*/
- public PageSnapshot(FullPageId fullPageId, long ptr, int pageSize) {
+ public PageSnapshot(FullPageId fullPageId, long ptr, int pageSize, int realPageSize) {
this.fullPageId = fullPageId;
+ this.realPageSize = realPageSize;
pageData = new byte[pageSize];
@@ -88,7 +97,7 @@ public class PageSnapshot extends WALRecord implements WalRecordCacheGroupAware{
try {
return "PageSnapshot [fullPageId = " + fullPageId() + ", page = [\n"
- + PageIO.printPage(addr, pageData.length)
+ + PageIO.printPage(addr, realPageSize)
+ "],\nsuper = ["
+ super.toString() + "]]";
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
index a555aae..667f8d9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/WALRecord.java
@@ -193,7 +193,13 @@ public abstract class WALRecord {
MVCC_DATA_PAGE_TX_STATE_HINT_UPDATED_RECORD,
/** */
- MVCC_DATA_PAGE_NEW_TX_STATE_HINT_UPDATED_RECORD;
+ MVCC_DATA_PAGE_NEW_TX_STATE_HINT_UPDATED_RECORD,
+
+ /** Encrypted WAL-record. */
+ ENCRYPTED_RECORD,
+
+ /** Ecnrypted data record */
+ ENCRYPTED_DATA_RECORD;
/** */
private static final RecordType[] VALS = RecordType.values();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertFragmentRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertFragmentRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertFragmentRecord.java
index 2b02bb57..650ae1e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertFragmentRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertFragmentRecord.java
@@ -57,7 +57,7 @@ public class DataPageInsertFragmentRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
AbstractDataPageIO io = PageIO.getPageIO(pageAddr);
- io.addRowFragment(PageIO.getPageId(pageAddr), pageAddr, payload, lastLink, pageMem.pageSize());
+ io.addRowFragment(PageIO.getPageId(pageAddr), pageAddr, payload, lastLink, pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertRecord.java
index 2c9a8e7..9b0637d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageInsertRecord.java
@@ -58,7 +58,7 @@ public class DataPageInsertRecord extends PageDeltaRecord {
AbstractDataPageIO io = PageIO.getPageIO(pageAddr);
- io.addRow(pageAddr, payload, pageMem.pageSize());
+ io.addRow(pageAddr, payload, pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccMarkUpdatedRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccMarkUpdatedRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccMarkUpdatedRecord.java
index 5e89f8e..907f4c0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccMarkUpdatedRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccMarkUpdatedRecord.java
@@ -60,7 +60,7 @@ public class DataPageMvccMarkUpdatedRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
DataPageIO io = PageIO.getPageIO(pageAddr);
- io.updateNewVersion(pageAddr, itemId, pageMem.pageSize(), newMvccCrd, newMvccCntr, newMvccOpCntr);
+ io.updateNewVersion(pageAddr, itemId, pageMem.realPageSize(groupId()), newMvccCrd, newMvccCntr, newMvccOpCntr);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateNewTxStateHintRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateNewTxStateHintRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateNewTxStateHintRecord.java
index 4a244a1..f3d235d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateNewTxStateHintRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateNewTxStateHintRecord.java
@@ -50,7 +50,7 @@ public class DataPageMvccUpdateNewTxStateHintRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
DataPageIO io = PageIO.getPageIO(pageAddr);
- io.updateNewTxState(pageAddr, itemId, pageMem.pageSize(), txState);
+ io.updateNewTxState(pageAddr, itemId, pageMem.realPageSize(groupId()), txState);
}
/** {@inheritDoc} */
[3/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes
#4167.
Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/package-info.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/package-info.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/package-info.java
new file mode 100644
index 0000000..71f1634
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains encryption SPI implementation based on standard jdk keystore.
+ */
+package org.apache.ignite.spi.encryption.keystore;
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/spi/encryption/noop/NoopEncryptionSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/noop/NoopEncryptionSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/noop/NoopEncryptionSpi.java
new file mode 100644
index 0000000..1de64d9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/noop/NoopEncryptionSpi.java
@@ -0,0 +1,101 @@
+/*
+ * 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.ignite.spi.encryption.noop;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.spi.IgniteSpiAdapter;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.IgniteSpiNoop;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * No operation {@code EncryptionSPI} implementation.
+ *
+ * @see EncryptionSpi
+ * @see KeystoreEncryptionSpi
+ */
+@IgniteSpiNoop
+public class NoopEncryptionSpi extends IgniteSpiAdapter implements EncryptionSpi {
+ /** {@inheritDoc} */
+ @Override public byte[] masterKeyDigest() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Serializable create() throws IgniteException {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void encrypt(ByteBuffer data, Serializable key, ByteBuffer res) {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void encryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res) {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] decrypt(byte[] data, Serializable key) {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void decryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res) {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] encryptKey(Serializable key) {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public Serializable decryptKey(byte[] key) {
+ throw new IgniteSpiException("You have to configure custom EncryptionSpi implementation.");
+ }
+
+ /** {@inheritDoc} */
+ @Override public int encryptedSize(int dataSize) {
+ return dataSize;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int encryptedSizeNoPadding(int dataSize) {
+ return dataSize;
+ }
+
+ @Override public int blockSize() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void spiStart(@Nullable String igniteInstanceName) throws IgniteSpiException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void spiStop() throws IgniteSpiException {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/spi/encryption/package-info.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/package-info.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/package-info.java
new file mode 100644
index 0000000..9805aaf
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains APIs for encryption SPI.
+ */
+package org.apache.ignite.spi.encryption;
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/AbstractEncryptionTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/AbstractEncryptionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/AbstractEncryptionTest.java
new file mode 100644
index 0000000..f267186
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/AbstractEncryptionTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.security.KeyStore;
+import java.util.HashSet;
+import java.util.Set;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.configuration.WALMode.FSYNC;
+import static org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi.CIPHER_ALGO;
+import static org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi.DEFAULT_MASTER_KEY_NAME;
+
+/**
+ * Abstract encryption test.
+ */
+public abstract class AbstractEncryptionTest extends GridCommonAbstractTest {
+ /** */
+ static final String ENCRYPTED_CACHE = "encrypted";
+
+ /** */
+ public static final String KEYSTORE_PATH =
+ IgniteUtils.resolveIgnitePath("modules/core/src/test/resources/tde.jks").getAbsolutePath();
+
+ /** */
+ static final String GRID_0 = "grid-0";
+
+ /** */
+ static final String GRID_1 = "grid-1";
+
+ /** */
+ public static final String KEYSTORE_PASSWORD = "love_sex_god";
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String name) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(name);
+
+ KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.setKeyStorePath(keystorePath());
+ encSpi.setKeyStorePassword(keystorePassword());
+
+ cfg.setEncryptionSpi(encSpi);
+
+ DataStorageConfiguration memCfg = new DataStorageConfiguration()
+ .setDefaultDataRegionConfiguration(
+ new DataRegionConfiguration()
+ .setMaxSize(10L * 1024 * 1024)
+ .setPersistenceEnabled(true))
+ .setPageSize(4 * 1024)
+ .setWalMode(FSYNC);
+
+ cfg.setDataStorageConfiguration(memCfg);
+
+ return cfg;
+ }
+
+ /** */
+ private char[] keystorePassword() {
+ return KEYSTORE_PASSWORD.toCharArray();
+ }
+
+ /** */
+ protected String keystorePath() {
+ return KEYSTORE_PATH;
+ }
+
+ /** */
+ void checkEncryptedCaches(IgniteEx grid0, IgniteEx grid1) {
+ Set<String> cacheNames = new HashSet<>(grid0.cacheNames());
+
+ cacheNames.addAll(grid1.cacheNames());
+
+ for (String cacheName : cacheNames) {
+ CacheConfiguration ccfg = grid1.cache(cacheName).getConfiguration(CacheConfiguration.class);
+
+ if (!ccfg.isEncryptionEnabled())
+ continue;
+
+ IgniteInternalCache<?, ?> encrypted0 = grid0.cachex(cacheName);
+
+ int grpId = CU.cacheGroupId(cacheName, ccfg.getGroupName());
+
+ assertNotNull(encrypted0);
+
+ IgniteInternalCache<?, ?> encrypted1 = grid1.cachex(cacheName);
+
+ assertNotNull(encrypted1);
+
+ assertTrue(encrypted1.configuration().isEncryptionEnabled());
+
+ KeystoreEncryptionKey encKey0 = (KeystoreEncryptionKey)grid0.context().encryption().groupKey(grpId);
+
+ assertNotNull(encKey0);
+ assertNotNull(encKey0.key());
+
+ if (!grid1.configuration().isClientMode()) {
+ KeystoreEncryptionKey encKey1 = (KeystoreEncryptionKey)grid1.context().encryption().groupKey(grpId);
+
+ assertNotNull(encKey1);
+ assertNotNull(encKey1.key());
+
+ assertEquals(encKey0.key(), encKey1.key());
+ }
+ else
+ assertNull(grid1.context().encryption().groupKey(grpId));
+ }
+
+ checkData(grid0);
+ }
+
+ /** */
+ protected void checkData(IgniteEx grid0) {
+ IgniteCache<Long, String> cache = grid0.cache(cacheName());
+
+ assertNotNull(cache);
+
+ for (long i=0; i<100; i++)
+ assertEquals("" + i, cache.get(i));
+ }
+
+ /** */
+ protected void createEncryptedCache(IgniteEx grid0, @Nullable IgniteEx grid1, String cacheName, String cacheGroup)
+ throws IgniteInterruptedCheckedException {
+ createEncryptedCache(grid0, grid1, cacheName, cacheGroup, true);
+ }
+
+ /** */
+ protected void createEncryptedCache(IgniteEx grid0, @Nullable IgniteEx grid1, String cacheName, String cacheGroup,
+ boolean putData) throws IgniteInterruptedCheckedException {
+ CacheConfiguration<Long, String> ccfg = new CacheConfiguration<Long, String>(cacheName)
+ .setWriteSynchronizationMode(FULL_SYNC)
+ .setGroupName(cacheGroup)
+ .setEncryptionEnabled(true);
+
+ IgniteCache<Long, String> cache = grid0.createCache(ccfg);
+
+ if (grid1 != null)
+ GridTestUtils.waitForCondition(() -> grid1.cachex(cacheName()) != null, 2_000L);
+
+ if (putData) {
+ for (long i = 0; i < 100; i++)
+ cache.put(i, "" + i);
+
+ for (long i = 0; i < 100; i++)
+ assertEquals("" + i, cache.get(i));
+ }
+ }
+
+ /**
+ * Starts tests grid instances.
+ *
+ * @param clnPersDir If {@code true} than before start persistence dir are cleaned.
+ * @return Started grids.
+ * @throws Exception If failed.
+ */
+ protected T2<IgniteEx, IgniteEx> startTestGrids(boolean clnPersDir) throws Exception {
+ if (clnPersDir)
+ cleanPersistenceDir();
+
+ IgniteEx grid0 = startGrid(GRID_0);
+
+ IgniteEx grid1 = startGrid(GRID_1);
+
+ grid0.cluster().active(true);
+
+ awaitPartitionMapExchange();
+
+ return new T2<>(grid0, grid1);
+ }
+
+ /** */
+ @NotNull protected String cacheName() {
+ return ENCRYPTED_CACHE;
+ }
+
+ /**
+ * Method to create new keystore.
+ * Use it whenever you need special keystore for an encryption tests.
+ */
+ @SuppressWarnings("unused")
+ protected File createKeyStore(String keystorePath) throws Exception {
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+
+ ks.load(null, null);
+
+ KeyGenerator gen = KeyGenerator.getInstance(CIPHER_ALGO);
+
+ gen.init(KeystoreEncryptionSpi.DEFAULT_KEY_SIZE);
+
+ SecretKey key = gen.generateKey();
+
+ ks.setEntry(
+ DEFAULT_MASTER_KEY_NAME,
+ new KeyStore.SecretKeyEntry(key),
+ new KeyStore.PasswordProtection(KEYSTORE_PASSWORD.toCharArray()));
+
+ File keyStoreFile = new File(keystorePath);
+
+ keyStoreFile.createNewFile();
+
+ try (OutputStream os = new FileOutputStream(keyStoreFile)) {
+ ks.store(os, KEYSTORE_PASSWORD.toCharArray());
+ }
+
+ return keyStoreFile;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheBigEntryTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheBigEntryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheBigEntryTest.java
new file mode 100644
index 0000000..deb72e4
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheBigEntryTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import java.util.Arrays;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests to check encryption of entry bigger then page size.
+ */
+public class EncryptedCacheBigEntryTest extends AbstractEncryptionTest {
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids(false);
+
+ cleanPersistenceDir();
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateEncryptedCacheWithBigEntry() throws Exception {
+ T2<IgniteEx, IgniteEx> grids = startTestGrids(true);
+
+ createEncryptedCache(grids.get1(), grids.get2(), cacheName(), null);
+
+ checkEncryptedCaches(grids.get1(), grids.get2());
+
+ int grpId = CU.cacheGroupId(cacheName(), null);
+
+ KeystoreEncryptionKey keyBeforeRestart =
+ (KeystoreEncryptionKey)grids.get1().context().encryption().groupKey(grpId);
+
+ stopAllGrids();
+
+ grids = startTestGrids(false);
+
+ checkEncryptedCaches(grids.get1(), grids.get2());
+
+ KeystoreEncryptionKey keyAfterRestart = (KeystoreEncryptionKey)grids.get1().context().encryption().groupKey(grpId);
+
+ assertNotNull(keyAfterRestart);
+ assertNotNull(keyAfterRestart.key());
+
+ assertEquals(keyBeforeRestart.key(), keyAfterRestart.key());
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void createEncryptedCache(IgniteEx grid0, @Nullable IgniteEx grid1, String cacheName,
+ String cacheGroup, boolean putData) throws IgniteInterruptedCheckedException {
+ CacheConfiguration<Integer, byte[]> ccfg = new CacheConfiguration<Integer, byte[]>(cacheName)
+ .setWriteSynchronizationMode(FULL_SYNC)
+ .setGroupName(cacheGroup)
+ .setEncryptionEnabled(true);
+
+ IgniteCache<Integer, byte[]> cache = grid0.createCache(ccfg);
+
+ if (grid1 != null)
+ GridTestUtils.waitForCondition(() -> grid1.cachex(cacheName()) != null, 2_000L);
+
+ if (putData) {
+ cache.put(1, bigArray(grid0));
+
+ assertTrue(Arrays.equals(bigArray(grid0), cache.get(1)));
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void checkData(IgniteEx grid0) {
+ IgniteCache<Integer, byte[]> cache = grid0.cache(cacheName());
+
+ assertTrue(Arrays.equals(bigArray(grid0), cache.get(1)));
+ }
+
+ /** */
+ private byte[] bigArray(IgniteEx grid) {
+ int arrSz = grid.configuration().getDataStorageConfiguration().getPageSize() * 3;
+
+ byte[] bigArr = new byte[arrSz];
+
+ for (int i=0; i<bigArr.length; i++)
+ bigArr[i] = (byte)i;
+
+ return bigArr;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheCreateTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheCreateTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheCreateTest.java
new file mode 100644
index 0000000..47d8d8f
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheCreateTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import com.google.common.primitives.Bytes;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/** */
+public class EncryptedCacheCreateTest extends AbstractEncryptionTest {
+ /** Non-persistent data region name. */
+ private static final String NO_PERSISTENCE_REGION = "no-persistence-region";
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ cleanPersistenceDir();
+
+ IgniteEx igniteEx = startGrid(0);
+
+ startGrid(1);
+
+ igniteEx.cluster().active(true);
+
+ awaitPartitionMapExchange();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String name) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(name);
+
+ DataStorageConfiguration memCfg = cfg.getDataStorageConfiguration();
+
+ memCfg.setDataRegionConfigurations(new DataRegionConfiguration()
+ .setMaxSize(10L * 1024 * 1024)
+ .setName(NO_PERSISTENCE_REGION)
+ .setPersistenceEnabled(false));
+
+ return cfg;
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateEncryptedCache() throws Exception {
+ CacheConfiguration<Long, String> ccfg = new CacheConfiguration<>(ENCRYPTED_CACHE);
+
+ ccfg.setEncryptionEnabled(true);
+
+ IgniteEx grid = grid(0);
+
+ grid.createCache(ccfg);
+
+ IgniteInternalCache<Object, Object> enc = grid.cachex(ENCRYPTED_CACHE);
+
+ assertNotNull(enc);
+
+ KeystoreEncryptionKey key =
+ (KeystoreEncryptionKey)grid.context().encryption().groupKey(CU.cacheGroupId(ENCRYPTED_CACHE, null));
+
+ assertNotNull(key);
+ assertNotNull(key.key());
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateEncryptedNotPersistedCacheFail() throws Exception {
+ fail("https://issues.apache.org/jira/browse/IGNITE-8640");
+
+ GridTestUtils.assertThrowsWithCause(() -> {
+ CacheConfiguration<Long, String> ccfg = new CacheConfiguration<>(NO_PERSISTENCE_REGION);
+
+ ccfg.setEncryptionEnabled(true);
+ ccfg.setDataRegionName(NO_PERSISTENCE_REGION);
+
+ grid(0).createCache(ccfg);
+ }, IgniteCheckedException.class);
+ }
+
+ /** @throws Exception If failed. */
+ public void testPersistedContentEncrypted() throws Exception {
+ IgniteCache<Integer, String> enc = grid(0).createCache(
+ new CacheConfiguration<Integer, String>(ENCRYPTED_CACHE)
+ .setEncryptionEnabled(true));
+
+ IgniteCache<Integer, String> plain = grid(0).createCache(new CacheConfiguration<>("plain-cache"));
+
+ assertNotNull(enc);
+
+ String encValPart = "AAAAAAAAAA";
+ String plainValPart = "BBBBBBBBBB";
+
+ StringBuilder longEncVal = new StringBuilder(encValPart.length()*100);
+ StringBuilder longPlainVal = new StringBuilder(plainValPart.length()*100);
+
+ for (int i = 0; i < 100; i++) {
+ longEncVal.append(encValPart);
+ longPlainVal.append(plainValPart);
+ }
+
+ enc.put(1, longEncVal.toString());
+ plain.put(1, longPlainVal.toString());
+
+ stopAllGrids(false);
+
+ byte[] encValBytes = encValPart.getBytes(StandardCharsets.UTF_8);
+ byte[] plainValBytes = plainValPart.getBytes(StandardCharsets.UTF_8);
+
+ final boolean[] plainBytesFound = {false};
+
+ Files.walk(U.resolveWorkDirectory(U.defaultWorkDirectory(), "db", false).toPath())
+ .filter(Files::isRegularFile)
+ .forEach(f -> {
+ try {
+ if (Files.size(f) == 0)
+ return;
+
+ byte[] fileBytes = Files.readAllBytes(f);
+
+ boolean notFound = Bytes.indexOf(fileBytes, encValBytes) == -1;
+
+ assertTrue("Value should be encrypted in persisted file. " + f.getFileName(), notFound);
+
+ plainBytesFound[0] = plainBytesFound[0] || Bytes.indexOf(fileBytes, plainValBytes) != -1;
+
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ assertTrue("Plain value should be found in persistent store", plainBytesFound[0]);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheDestroyTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheDestroyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheDestroyTest.java
new file mode 100644
index 0000000..11855ec
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheDestroyTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import java.util.Collection;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+
+import static org.apache.ignite.internal.managers.encryption.GridEncryptionManager.ENCRYPTION_KEY_PREFIX;
+
+/**
+ */
+public class EncryptedCacheDestroyTest extends AbstractEncryptionTest {
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEncryptedCacheDestroy() throws Exception {
+ T2<IgniteEx, IgniteEx> grids = startTestGrids(true);
+
+ createEncryptedCache(grids.get1(), grids.get2(), cacheName(), null);
+
+ checkEncryptedCaches(grids.get1(), grids.get2());
+
+ String encryptedCacheName = cacheName();
+
+ grids.get1().destroyCache(encryptedCacheName);
+
+ checkCacheDestroyed(grids.get2(), encryptedCacheName, null, true);
+
+ stopAllGrids(true);
+
+ grids = startTestGrids(false);
+
+ checkCacheDestroyed(grids.get1(), encryptedCacheName, null, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testEncryptedCacheFromGroupDestroy() throws Exception {
+ T2<IgniteEx, IgniteEx> grids = startTestGrids(true);
+
+ String encCacheName = cacheName();
+
+ String grpName = "group1";
+
+ createEncryptedCache(grids.get1(), grids.get2(), encCacheName + "2", grpName);
+ createEncryptedCache(grids.get1(), grids.get2(), encCacheName, grpName);
+
+ checkEncryptedCaches(grids.get1(), grids.get2());
+
+ grids.get1().destroyCache(encCacheName);
+
+ checkCacheDestroyed(grids.get2(), encCacheName, grpName, false);
+
+ stopAllGrids(true);
+
+ grids = startTestGrids(false);
+
+ checkCacheDestroyed(grids.get1(), encCacheName, grpName, false);
+
+ grids.get1().destroyCache(encCacheName + "2");
+
+ checkCacheDestroyed(grids.get1(), encCacheName + "2", grpName, true);
+
+ stopAllGrids(true);
+
+ grids = startTestGrids(false);
+
+ checkCacheDestroyed(grids.get1(), encCacheName, grpName, true);
+
+ checkCacheDestroyed(grids.get1(), encCacheName + "2", grpName, true);
+ }
+
+ /** */
+ private void checkCacheDestroyed(IgniteEx grid, String encCacheName, String grpName, boolean keyShouldBeEmpty)
+ throws Exception {
+ awaitPartitionMapExchange();
+
+ Collection<String> cacheNames = grid.cacheNames();
+
+ for (String cacheName : cacheNames) {
+ if (cacheName.equals(encCacheName))
+ fail(encCacheName + " should be destroyed.");
+ }
+
+ int grpId = CU.cacheGroupId(encCacheName, grpName);
+
+ KeystoreEncryptionKey encKey = (KeystoreEncryptionKey)grid.context().encryption().groupKey(grpId);
+ MetaStorage metaStore = grid.context().cache().context().database().metaStorage();
+
+ if (keyShouldBeEmpty) {
+ assertNull(encKey);
+
+ assertNull(metaStore.getData(ENCRYPTION_KEY_PREFIX + grpId));
+ } else {
+ assertNotNull(encKey);
+
+ assertNotNull(metaStore.getData(ENCRYPTION_KEY_PREFIX + grpId));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheGroupCreateTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheGroupCreateTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheGroupCreateTest.java
new file mode 100644
index 0000000..56f578d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheGroupCreateTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.testframework.GridTestUtils;
+
+/**
+ */
+public class EncryptedCacheGroupCreateTest extends AbstractEncryptionTest {
+ /** */
+ public static final String ENCRYPTED_GROUP = "encrypted-group";
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ cleanPersistenceDir();
+
+ IgniteEx igniteEx = startGrid(0);
+
+ startGrid(1);
+
+ igniteEx.cluster().active(true);
+
+ awaitPartitionMapExchange();
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateEncryptedCacheGroup() throws Exception {
+ KeystoreEncryptionKey key = createEncryptedCache(ENCRYPTED_CACHE, ENCRYPTED_GROUP);
+
+ CacheConfiguration<Long, String> ccfg = new CacheConfiguration<>(ENCRYPTED_CACHE + "2");
+
+ ccfg.setEncryptionEnabled(true);
+ ccfg.setGroupName(ENCRYPTED_GROUP);
+
+ IgniteEx grid = grid(0);
+
+ grid.createCache(ccfg);
+
+ IgniteInternalCache<Object, Object> encrypted2 = grid.cachex(ENCRYPTED_CACHE + "2");
+
+ GridEncryptionManager encMgr = encrypted2.context().kernalContext().encryption();
+
+ KeystoreEncryptionKey key2 = (KeystoreEncryptionKey)encMgr.groupKey(CU.cacheGroupId(ENCRYPTED_CACHE, ENCRYPTED_GROUP));
+
+ assertNotNull(key2);
+ assertNotNull(key2.key());
+
+ assertEquals(key.key(), key2.key());
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateNotEncryptedCacheInEncryptedGroupFails() throws Exception {
+ createEncryptedCache(ENCRYPTED_CACHE + "3", ENCRYPTED_GROUP + "3");
+
+ IgniteEx grid = grid(0);
+
+ GridTestUtils.assertThrowsWithCause(() -> {
+ grid.createCache(new CacheConfiguration<>(ENCRYPTED_CACHE + "4")
+ .setEncryptionEnabled(false)
+ .setGroupName(ENCRYPTED_GROUP + "3"));
+ }, IgniteCheckedException.class);
+ }
+
+ /** */
+ private KeystoreEncryptionKey createEncryptedCache(String cacheName, String grpName) {
+ CacheConfiguration<Long, String> ccfg = new CacheConfiguration<>(cacheName);
+
+ ccfg.setEncryptionEnabled(true);
+ ccfg.setGroupName(grpName);
+
+ IgniteEx grid = grid(0);
+
+ grid.createCache(ccfg);
+
+ IgniteInternalCache<Object, Object> enc = grid.cachex(cacheName);
+
+ assertNotNull(enc);
+
+ KeystoreEncryptionKey key =
+ (KeystoreEncryptionKey)grid.context().encryption().groupKey(CU.cacheGroupId(cacheName, grpName));
+
+ assertNotNull(key);
+ assertNotNull(key.key());
+
+ return key;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheNodeJoinTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheNodeJoinTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheNodeJoinTest.java
new file mode 100644
index 0000000..41a250c
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheNodeJoinTest.java
@@ -0,0 +1,237 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+
+import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
+
+/**
+ */
+public class EncryptedCacheNodeJoinTest extends AbstractEncryptionTest {
+ /** */
+ private static final String GRID_2 = "grid-2";
+
+ /** */
+ private static final String GRID_3 = "grid-3";
+
+ /** */
+ private static final String GRID_4 = "grid-4";
+
+ /** */
+ private static final String GRID_5 = "grid-5";
+
+ /** */
+ public static final String CLIENT = "client";
+
+ /** */
+ private boolean configureCache;
+
+ /** */
+ private static final String KEYSTORE_PATH_2 =
+ IgniteUtils.resolveIgnitePath("modules/core/src/test/resources/other_tde_keystore.jks").getAbsolutePath();
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ cleanPersistenceDir();
+
+ configureCache = false;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String grid) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(grid);
+
+ cfg.setConsistentId(grid);
+
+ if (grid.equals(GRID_0) ||
+ grid.equals(GRID_2) ||
+ grid.equals(GRID_3) ||
+ grid.equals(GRID_4) ||
+ grid.equals(GRID_5)) {
+ KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.setKeyStorePath(grid.equals(GRID_2) ? KEYSTORE_PATH_2 : KEYSTORE_PATH);
+ encSpi.setKeyStorePassword(KEYSTORE_PASSWORD.toCharArray());
+
+ cfg.setEncryptionSpi(encSpi);
+ }
+ else
+ cfg.setEncryptionSpi(null);
+
+ cfg.setClientMode(grid.equals(CLIENT));
+
+ if (configureCache)
+ cfg.setCacheConfiguration(cacheConfiguration(grid));
+
+ return cfg;
+ }
+
+ /** */
+ protected CacheConfiguration cacheConfiguration(String gridName) {
+ CacheConfiguration ccfg = defaultCacheConfiguration();
+
+ ccfg.setName(cacheName());
+ ccfg.setEncryptionEnabled(gridName.equals(GRID_0));
+
+ return ccfg;
+ }
+
+ /** */
+ public void testNodeCantJoinWithoutEncryptionSpi() throws Exception {
+ startGrid(GRID_0);
+
+ assertThrowsWithCause(() -> {
+ try {
+ startGrid(GRID_1);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+
+ /** */
+ public void testNodeCantJoinWithDifferentKeyStore() throws Exception {
+ startGrid(GRID_0);
+
+ assertThrowsWithCause(() -> {
+ try {
+ startGrid(GRID_2);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+
+ /** */
+ public void testNodeCanJoin() throws Exception {
+ startGrid(GRID_0);
+
+ startGrid(GRID_3).cluster().active(true);
+ }
+
+ /** */
+ public void testNodeCantJoinWithDifferentCacheKeys() throws Exception {
+ IgniteEx grid0 = startGrid(GRID_0);
+ startGrid(GRID_3);
+
+ grid0.cluster().active(true);
+
+ stopGrid(GRID_3, false);
+
+ createEncryptedCache(grid0, null, cacheName(), null, false);
+
+ stopGrid(GRID_0, false);
+ IgniteEx grid3 = startGrid(GRID_3);
+
+ grid3.cluster().active(true);
+
+ createEncryptedCache(grid3, null, cacheName(), null, false);
+
+ assertThrowsWithCause(() -> {
+ try {
+ startGrid(GRID_0);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+
+ /** */
+ public void testThirdNodeCanJoin() throws Exception {
+ IgniteEx grid0 = startGrid(GRID_0);
+
+ IgniteEx grid3 = startGrid(GRID_3);
+
+ grid3.cluster().active(true);
+
+ createEncryptedCache(grid0, grid3, cacheName(), null);
+
+ checkEncryptedCaches(grid0, grid3);
+
+ IgniteEx grid4 = startGrid(GRID_4);
+
+ awaitPartitionMapExchange();
+
+ checkEncryptedCaches(grid0, grid4);
+ }
+
+ /** */
+ public void testClientNodeJoin() throws Exception {
+ IgniteEx grid0 = startGrid(GRID_0);
+
+ IgniteEx grid3 = startGrid(GRID_3);
+
+ grid3.cluster().active(true);
+
+ IgniteEx client = startGrid(CLIENT);
+
+ createEncryptedCache(client, grid0, cacheName(), null);
+ }
+
+ /** */
+ public void testNodeCantJoinWithSameNameButNotEncCache() throws Exception {
+ configureCache = true;
+
+ IgniteEx grid0 = startGrid(GRID_0);
+
+ grid0.cluster().active(true);
+
+ assertThrowsWithCause(() -> {
+ try {
+ startGrid(GRID_5);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+
+ /** */
+ public void testNodeCantJoinWithSameNameButEncCache() throws Exception {
+ configureCache = true;
+
+ IgniteEx grid0 = startGrid(GRID_5);
+
+ grid0.cluster().active(true);
+
+ assertThrowsWithCause(() -> {
+ try {
+ startGrid(GRID_0);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCachePreconfiguredRestartTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCachePreconfiguredRestartTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCachePreconfiguredRestartTest.java
new file mode 100644
index 0000000..2e13340
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCachePreconfiguredRestartTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.jetbrains.annotations.NotNull;
+
+/** */
+public class EncryptedCachePreconfiguredRestartTest extends EncryptedCacheRestartTest {
+ /** */
+ private boolean differentCachesOnNodes;
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ cleanPersistenceDir();
+ }
+
+ /** @throws Exception If failed. */
+ public void testDifferentPreconfiguredCachesOnNodes() throws Exception {
+ differentCachesOnNodes = true;
+
+ super.testCreateEncryptedCache();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void testCreateEncryptedCache() throws Exception {
+ differentCachesOnNodes = false;
+
+ super.testCreateEncryptedCache();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ String cacheName = ENCRYPTED_CACHE + (differentCachesOnNodes ? "." + igniteInstanceName : "");
+
+ CacheConfiguration ccfg = new CacheConfiguration(cacheName)
+ .setEncryptionEnabled(true);
+
+ cfg.setCacheConfiguration(ccfg);
+
+ return cfg;
+ }
+
+ /**
+ * @return Cache name.
+ */
+ @NotNull @Override protected String cacheName() {
+ return ENCRYPTED_CACHE + (differentCachesOnNodes ? "." + GRID_1 : "");
+ }
+
+ /**
+ * Creates encrypted cache.
+ */
+ @Override protected void createEncryptedCache(IgniteEx grid0, IgniteEx grid1, String cacheName, String groupName) {
+ IgniteCache<Long, String> cache = grid0.cache(cacheName());
+
+ for (long i=0; i<100; i++)
+ cache.put(i, "" + i);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheRestartTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheRestartTest.java b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheRestartTest.java
new file mode 100644
index 0000000..2b01072
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/encryption/EncryptedCacheRestartTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.ignite.internal.encryption;
+
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+
+/** */
+public class EncryptedCacheRestartTest extends AbstractEncryptionTest {
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids(false);
+
+ cleanPersistenceDir();
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateEncryptedCache() throws Exception {
+ T2<IgniteEx, IgniteEx> grids = startTestGrids(true);
+
+ createEncryptedCache(grids.get1(), grids.get2(), cacheName(), null);
+
+ checkEncryptedCaches(grids.get1(), grids.get2());
+
+ int grpId = CU.cacheGroupId(cacheName(), null);
+
+ KeystoreEncryptionKey keyBeforeRestart = (KeystoreEncryptionKey)grids.get1().context().encryption().groupKey(grpId);
+
+ stopAllGrids();
+
+ grids = startTestGrids(false);
+
+ checkEncryptedCaches(grids.get1(), grids.get2());
+
+ KeystoreEncryptionKey keyAfterRestart = (KeystoreEncryptionKey)grids.get1().context().encryption().groupKey(grpId);
+
+ assertNotNull(keyAfterRestart);
+ assertNotNull(keyAfterRestart.key());
+
+ assertEquals(keyBeforeRestart.key(), keyAfterRestart.key());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoLoadSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoLoadSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoLoadSelfTest.java
index c5988e3..b393634 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoLoadSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoLoadSelfTest.java
@@ -77,8 +77,8 @@ public class PageMemoryNoLoadSelfTest extends GridCommonAbstractTest {
", page2Id=" + fullId2.pageId() + ", page2=" + page2 + ']');
try {
- writePage(mem, fullId1.pageId(), page1, 1);
- writePage(mem, fullId2.pageId(), page2, 2);
+ writePage(mem, fullId1, page1, 1);
+ writePage(mem, fullId2, page2, 2);
readPage(mem, fullId1.pageId(), page1, 1);
readPage(mem, fullId2.pageId(), page2, 2);
@@ -149,7 +149,7 @@ public class PageMemoryNoLoadSelfTest extends GridCommonAbstractTest {
if (i % 64 == 0)
info("Writing page [idx=" + i + ", pageId=" + fullId.pageId() + ", page=" + page + ']');
- writePage(mem, fullId.pageId(), page, i + 1);
+ writePage(mem, fullId, page, i + 1);
}
finally {
mem.releasePage(fullId.groupId(), fullId.pageId(), page);
@@ -230,7 +230,7 @@ public class PageMemoryNoLoadSelfTest extends GridCommonAbstractTest {
assertNotNull(pageAddr);
try {
- PAGE_IO.initNewPage(pageAddr, id.pageId(), mem.pageSize());
+ PAGE_IO.initNewPage(pageAddr, id.pageId(), mem.realPageSize(id.groupId()));
long updId = PageIdUtils.rotatePageId(id.pageId());
@@ -332,21 +332,21 @@ public class PageMemoryNoLoadSelfTest extends GridCommonAbstractTest {
/**
* @param mem Page memory.
- * @param pageId Page ID.
+ * @param fullId Page ID.
* @param page Page pointer.
* @param val Value to write.
*/
- private void writePage(PageMemory mem, long pageId, long page, int val) {
- long pageAddr = mem.writeLock(-1, pageId, page);
+ private void writePage(PageMemory mem, FullPageId fullId, long page, int val) {
+ long pageAddr = mem.writeLock(-1, fullId.pageId(), page);
try {
- PAGE_IO.initNewPage(pageAddr, pageId, mem.pageSize());
+ PAGE_IO.initNewPage(pageAddr, fullId.pageId(), mem.realPageSize(fullId.groupId()));
for (int i = PageIO.COMMON_HEADER_END; i < PAGE_SIZE; i++)
PageUtils.putByte(pageAddr, i, (byte)val);
}
finally {
- mem.writeUnlock(-1, pageId, page, null, true);
+ mem.writeUnlock(-1, fullId.pageId(), page, null, true);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsRecoveryAfterFileCorruptionTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsRecoveryAfterFileCorruptionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsRecoveryAfterFileCorruptionTest.java
index af6c8b7..15205e0 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsRecoveryAfterFileCorruptionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgnitePdsRecoveryAfterFileCorruptionTest.java
@@ -202,7 +202,7 @@ public class IgnitePdsRecoveryAfterFileCorruptionTest extends GridCommonAbstract
final long pageAddr = mem.writeLock(fullId.groupId(), fullId.pageId(), page);
try {
- pageIO.initNewPage(pageAddr, fullId.pageId(), mem.pageSize());
+ pageIO.initNewPage(pageAddr, fullId.pageId(), mem.realPageSize(fullId.groupId()));
}
finally {
mem.writeUnlock(fullId.groupId(), fullId.pageId(), page, null, true);
@@ -261,7 +261,7 @@ public class IgnitePdsRecoveryAfterFileCorruptionTest extends GridCommonAbstract
try {
long pageAddr = mem.readLock(fullId.groupId(), fullId.pageId(), page);
- for (int j = PageIO.COMMON_HEADER_END; j < mem.pageSize(); j += 4)
+ for (int j = PageIO.COMMON_HEADER_END; j < mem.realPageSize(fullId.groupId()); j += 4)
assertEquals(j + (int)fullId.pageId(), PageUtils.getInt(pageAddr, j));
mem.readUnlock(fullId.groupId(), fullId.pageId(), page);
@@ -305,7 +305,7 @@ public class IgnitePdsRecoveryAfterFileCorruptionTest extends GridCommonAbstract
PageIO.setPageId(pageAddr, fullId.pageId());
try {
- for (int j = PageIO.COMMON_HEADER_END; j < mem.pageSize(); j += 4)
+ for (int j = PageIO.COMMON_HEADER_END; j < mem.realPageSize(fullId.groupId()); j += 4)
PageUtils.putInt(pageAddr, j, j + (int)fullId.pageId());
}
finally {
@@ -346,7 +346,7 @@ public class IgnitePdsRecoveryAfterFileCorruptionTest extends GridCommonAbstract
cp += cpEnd - cpStart;
tmpBuf.rewind();
- for (int j = PageIO.COMMON_HEADER_END; j < mem.pageSize(); j += 4)
+ for (int j = PageIO.COMMON_HEADER_END; j < mem.realPageSize(fullId.groupId()); j += 4)
assertEquals(j + (int)fullId.pageId(), tmpBuf.getInt(j));
tmpBuf.rewind();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsCheckpointSimulationWithRealCpDisabledTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsCheckpointSimulationWithRealCpDisabledTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsCheckpointSimulationWithRealCpDisabledTest.java
index 5fa618b..620814f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsCheckpointSimulationWithRealCpDisabledTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsCheckpointSimulationWithRealCpDisabledTest.java
@@ -238,12 +238,13 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
long pageAddr = mem.writeLock(fullId.groupId(), fullId.pageId(), page);
try {
- DataPageIO.VERSIONS.latest().initNewPage(pageAddr, fullId.pageId(), mem.pageSize());
+ DataPageIO.VERSIONS.latest().initNewPage(pageAddr, fullId.pageId(),
+ mem.realPageSize(fullId.groupId()));
for (int i = PageIO.COMMON_HEADER_END + DataPageIO.ITEMS_OFF; i < mem.pageSize(); i++)
PageUtils.putByte(pageAddr, i, (byte)0xAB);
- PageIO.printPage(pageAddr, mem.pageSize());
+ PageIO.printPage(pageAddr, mem.realPageSize(fullId.groupId()));
}
finally {
mem.writeUnlock(fullId.groupId(), fullId.pageId(), page, null, true);
@@ -544,7 +545,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
long pageAddr = mem.writeLock(fullId.groupId(), fullId.pageId(), page);
try {
- pageIO.initNewPage(pageAddr, fullId.pageId(), mem.pageSize());
+ pageIO.initNewPage(pageAddr, fullId.pageId(), mem.realPageSize(fullId.groupId()));
assertTrue(mem.isDirty(fullId.groupId(), fullId.pageId(), page));
}
@@ -632,7 +633,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
long pageAddr = mem.writeLock(fullId.groupId(), fullId.pageId(), page);
try {
- DataPageIO.VERSIONS.latest().initNewPage(pageAddr, fullId.pageId(), mem.pageSize());
+ DataPageIO.VERSIONS.latest().initNewPage(pageAddr, fullId.pageId(), mem.realPageSize(fullId.groupId()));
ThreadLocalRandom rnd = ThreadLocalRandom.current();
@@ -707,7 +708,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
long pageAddr = mem.readLock(fullId.groupId(), fullId.pageId(), page);
try {
- for (int i = PageIO.COMMON_HEADER_END; i < mem.pageSize(); i++) {
+ for (int i = PageIO.COMMON_HEADER_END; i < mem.realPageSize(fullId.groupId()); i++) {
int expState = state & 0xFF;
int pageState = PageUtils.getByte(pageAddr, i) & 0xFF;
int walState = walData[i] & 0xFF;
@@ -818,7 +819,8 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
", bhc=" + U.hexLong(System.identityHashCode(pageAddr)) +
", page=" + U.hexLong(System.identityHashCode(page)) + ']');
- for (int i = PageIO.COMMON_HEADER_END; i < mem.pageSize(); i++)
+ for (int i = PageIO.COMMON_HEADER_END; i < mem.realPageSize(fullId.groupId());
+ i++) {
assertEquals("Verify page failed [fullId=" + fullId +
", i=" + i +
", state=" + state +
@@ -826,6 +828,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
", bhc=" + U.hexLong(System.identityHashCode(pageAddr)) +
", page=" + U.hexLong(System.identityHashCode(page)) + ']',
state & 0xFF, PageUtils.getByte(pageAddr, i) & 0xFF);
+ }
}
state = (state + 1) & 0xFF;
@@ -836,7 +839,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
", bhc=" + U.hexLong(System.identityHashCode(pageAddr)) +
", page=" + U.hexLong(System.identityHashCode(page)) + ']');
- for (int i = PageIO.COMMON_HEADER_END; i < mem.pageSize(); i++)
+ for (int i = PageIO.COMMON_HEADER_END; i < mem.realPageSize(fullId.groupId()); i++)
PageUtils.putByte(pageAddr, i, (byte)state);
resMap.put(fullId, state);
@@ -926,7 +929,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
Integer first = null;
- for (int i = PageIO.COMMON_HEADER_END; i < mem.pageSize(); i++) {
+ for (int i = PageIO.COMMON_HEADER_END; i < mem.realPageSize(fullId.groupId()); i++) {
int val = tmpBuf.get(i) & 0xFF;
if (first == null)
@@ -1027,7 +1030,7 @@ public class IgnitePdsCheckpointSimulationWithRealCpDisabledTest extends GridCom
final long pageAddr = mem.writeLock(fullId.groupId(), fullId.pageId(), page);
try {
- pageIO.initNewPage(pageAddr, fullId.pageId(), mem.pageSize());
+ pageIO.initNewPage(pageAddr, fullId.pageId(), mem.realPageSize(fullId.groupId()));
}
finally {
mem.writeUnlock(fullId.groupId(), fullId.pageId(), page, null, true);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsPageReplacementTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsPageReplacementTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsPageReplacementTest.java
index 432393e..2697c01 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsPageReplacementTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/file/IgnitePdsPageReplacementTest.java
@@ -201,7 +201,7 @@ public class IgnitePdsPageReplacementTest extends GridCommonAbstractTest {
final long pageAddr = mem.writeLock(fullId.groupId(), fullId.pageId(), page);
try {
- pageIO.initNewPage(pageAddr, fullId.pageId(), mem.pageSize());
+ pageIO.initNewPage(pageAddr, fullId.pageId(), mem.realPageSize(fullId.groupId()));
}
finally {
mem.writeUnlock(fullId.groupId(), fullId.pageId(), page, null, true);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalCompactionTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalCompactionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalCompactionTest.java
index e617455..dcc2280 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalCompactionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/WalCompactionTest.java
@@ -149,8 +149,10 @@ public class WalCompactionTest extends GridCommonAbstractTest {
}
// Spam WAL to move all data records to compressible WAL zone.
- for (int i = 0; i < WAL_SEGMENT_SIZE / DFLT_PAGE_SIZE * 2; i++)
- ig.context().cache().context().wal().log(new PageSnapshot(new FullPageId(-1, -1), new byte[DFLT_PAGE_SIZE]));
+ for (int i = 0; i < WAL_SEGMENT_SIZE / DFLT_PAGE_SIZE * 2; i++) {
+ ig.context().cache().context().wal().log(new PageSnapshot(new FullPageId(-1, -1), new byte[DFLT_PAGE_SIZE],
+ DFLT_PAGE_SIZE));
+ }
// WAL archive segment is allowed to be compressed when it's at least one checkpoint away from current WAL head.
ig.context().cache().context().database().wakeupForCheckpoint("Forced checkpoint").get();
@@ -347,8 +349,10 @@ public class WalCompactionTest extends GridCommonAbstractTest {
}
// Spam WAL to move all data records to compressible WAL zone.
- for (int i = 0; i < WAL_SEGMENT_SIZE / DFLT_PAGE_SIZE * 2; i++)
- ig.context().cache().context().wal().log(new PageSnapshot(new FullPageId(-1, -1), new byte[DFLT_PAGE_SIZE]));
+ for (int i = 0; i < WAL_SEGMENT_SIZE / DFLT_PAGE_SIZE * 2; i++) {
+ ig.context().cache().context().wal().log(new PageSnapshot(new FullPageId(-1, -1), new byte[DFLT_PAGE_SIZE],
+ DFLT_PAGE_SIZE));
+ }
// WAL archive segment is allowed to be compressed when it's at least one checkpoint away from current WAL head.
ig.context().cache().context().database().wakeupForCheckpoint("Forced checkpoint").get();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
index 7719b43..bb0c416 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
@@ -17,17 +17,25 @@
package org.apache.ignite.internal.processors.cache.persistence.pagemem;
+import java.util.Collections;
import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.persistence.CheckpointWriteProgressSupplier;
import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.database.BPlusTreeSelfTest;
+import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
+import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
import org.apache.ignite.internal.util.typedef.CIX3;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
+import org.mockito.Mockito;
/**
*
@@ -44,8 +52,18 @@ public class BPlusTreePageMemoryImplTest extends BPlusTreeSelfTest {
DirectMemoryProvider provider = new UnsafeMemoryProvider(log);
+ IgniteConfiguration cfg = new IgniteConfiguration();
+
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
+
+ GridTestKernalContext cctx = new GridTestKernalContext(log, cfg);
+
+ cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
+ cctx.add(new GridInternalSubscriptionProcessor(cctx));
+ cctx.add(new GridEncryptionManager(cctx));
+
GridCacheSharedContext<Object, Object> sharedCtx = new GridCacheSharedContext<>(
- new GridTestKernalContext(log),
+ cctx,
null,
null,
null,
@@ -78,7 +96,7 @@ public class BPlusTreePageMemoryImplTest extends BPlusTreeSelfTest {
() -> true,
new DataRegionMetricsImpl(new DataRegionConfiguration()),
PageMemoryImpl.ThrottlingPolicy.DISABLED,
- null
+ Mockito.mock(CheckpointWriteProgressSupplier.class)
);
mem.start();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
index 71eb129..71e308b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
@@ -17,7 +17,10 @@
package org.apache.ignite.internal.processors.cache.persistence.pagemem;
+import java.util.Collections;
import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
@@ -27,7 +30,10 @@ import org.apache.ignite.internal.processors.cache.persistence.CheckpointWritePr
import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.database.BPlusTreeReuseSelfTest;
+import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
+import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
import org.apache.ignite.internal.util.lang.GridInClosure3X;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
import org.mockito.Mockito;
@@ -46,8 +52,18 @@ public class BPlusTreeReuseListPageMemoryImplTest extends BPlusTreeReuseSelfTest
DirectMemoryProvider provider = new UnsafeMemoryProvider(log);
+ IgniteConfiguration cfg = new IgniteConfiguration();
+
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
+
+ GridTestKernalContext cctx = new GridTestKernalContext(log, cfg);
+
+ cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
+ cctx.add(new GridInternalSubscriptionProcessor(cctx));
+ cctx.add(new GridEncryptionManager(cctx));
+
GridCacheSharedContext<Object, Object> sharedCtx = new GridCacheSharedContext<>(
- new GridTestKernalContext(log),
+ cctx,
null,
null,
null,
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
index 5c965b1..b6031fa 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
@@ -36,12 +36,14 @@ import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.persistence.CheckpointWriteProgressSupplier;
import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.util.GridMultiCollectionWrapper;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.logger.NullLogger;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.testframework.GridTestUtils;
import org.jetbrains.annotations.NotNull;
import org.junit.Rule;
@@ -231,7 +233,8 @@ public class IgnitePageMemReplaceDelayedWriteUnitTest {
DirectMemoryProvider provider = new UnsafeMemoryProvider(log);
PageMemoryImpl memory = new PageMemoryImpl(provider, sizes, sctx, pageSize,
- pageWriter, null, () -> true, memMetrics, PageMemoryImpl.ThrottlingPolicy.DISABLED, null);
+ pageWriter, null, () -> true, memMetrics, PageMemoryImpl.ThrottlingPolicy.DISABLED,
+ mock(CheckpointWriteProgressSupplier.class));
memory.start();
return memory;
@@ -244,6 +247,8 @@ public class IgnitePageMemReplaceDelayedWriteUnitTest {
@NotNull private IgniteConfiguration getConfiguration(long overallSize) {
IgniteConfiguration cfg = new IgniteConfiguration();
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
+
cfg.setDataStorageConfiguration(
new DataStorageConfiguration()
.setDefaultDataRegionConfiguration(
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
index 43fbb6e..d3530b4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
@@ -18,18 +18,26 @@
package org.apache.ignite.internal.processors.cache.persistence.pagemem;
import java.io.File;
+import java.util.Collections;
import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.file.MappedFileMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.persistence.CheckpointWriteProgressSupplier;
import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.database.IndexStorageSelfTest;
+import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
+import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
import org.apache.ignite.internal.util.lang.GridInClosure3X;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
+import org.mockito.Mockito;
/**
*
@@ -59,8 +67,18 @@ public class IndexStoragePageMemoryImplTest extends IndexStorageSelfTest {
DirectMemoryProvider provider = new MappedFileMemoryProvider(log(), allocationPath);
+ IgniteConfiguration cfg = new IgniteConfiguration();
+
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
+
+ GridTestKernalContext cctx = new GridTestKernalContext(log, cfg);
+
+ cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
+ cctx.add(new GridInternalSubscriptionProcessor(cctx));
+ cctx.add(new GridEncryptionManager(cctx));
+
GridCacheSharedContext<Object, Object> sharedCtx = new GridCacheSharedContext<>(
- new GridTestKernalContext(log),
+ cctx,
null,
null,
null,
@@ -93,7 +111,7 @@ public class IndexStoragePageMemoryImplTest extends IndexStorageSelfTest {
() -> true,
new DataRegionMetricsImpl(new DataRegionConfiguration()),
PageMemoryImpl.ThrottlingPolicy.DISABLED,
- null
+ Mockito.mock(CheckpointWriteProgressSupplier.class)
);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
index 52aff0c..83e1894 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
@@ -18,7 +18,10 @@
package org.apache.ignite.internal.processors.cache.persistence.pagemem;
import java.io.File;
+import java.util.Collections;
import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.file.MappedFileMemoryProvider;
import org.apache.ignite.internal.pagemem.FullPageId;
@@ -26,11 +29,16 @@ import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.impl.PageMemoryNoLoadSelfTest;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.persistence.CheckpointLockStateChecker;
+import org.apache.ignite.internal.processors.cache.persistence.CheckpointWriteProgressSupplier;
import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
+import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
+import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
import org.apache.ignite.internal.util.lang.GridInClosure3X;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
+import org.mockito.Mockito;
/**
*
@@ -49,8 +57,18 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
DirectMemoryProvider provider = new MappedFileMemoryProvider(log(), memDir);
+ IgniteConfiguration cfg = new IgniteConfiguration();
+
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
+
+ GridTestKernalContext cctx = new GridTestKernalContext(log, cfg);
+
+ cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
+ cctx.add(new GridInternalSubscriptionProcessor(cctx));
+ cctx.add(new GridEncryptionManager(cctx));
+
GridCacheSharedContext<Object, Object> sharedCtx = new GridCacheSharedContext<>(
- new GridTestKernalContext(log),
+ cctx,
null,
null,
null,
@@ -88,7 +106,7 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
},
new DataRegionMetricsImpl(new DataRegionConfiguration()),
PageMemoryImpl.ThrottlingPolicy.DISABLED,
- null
+ Mockito.mock(CheckpointWriteProgressSupplier.class)
);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
index 000131a..fe79105 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.failure.NoOpFailureHandler;
import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
@@ -44,8 +45,10 @@ import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDataba
import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
import org.apache.ignite.internal.processors.failure.FailureProcessor;
import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
+import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
import org.apache.ignite.internal.util.lang.GridInClosure3X;
import org.apache.ignite.plugin.PluginProvider;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
@@ -271,9 +274,13 @@ public class PageMemoryImplTest extends GridCommonAbstractTest {
IgniteConfiguration igniteCfg = new IgniteConfiguration();
igniteCfg.setDataStorageConfiguration(new DataStorageConfiguration());
igniteCfg.setFailureHandler(new NoOpFailureHandler());
+ igniteCfg.setEncryptionSpi(new NoopEncryptionSpi());
GridTestKernalContext kernalCtx = new GridTestKernalContext(new GridTestLog4jLogger(), igniteCfg);
+
kernalCtx.add(new IgnitePluginProcessor(kernalCtx, igniteCfg, Collections.<PluginProvider>emptyList()));
+ kernalCtx.add(new GridInternalSubscriptionProcessor(kernalCtx));
+ kernalCtx.add(new GridEncryptionManager(kernalCtx));
FailureProcessor failureProc = new FailureProcessor(kernalCtx);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/memtracker/PageMemoryTracker.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/memtracker/PageMemoryTracker.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/memtracker/PageMemoryTracker.java
index 661b6c7..09cacfb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/memtracker/PageMemoryTracker.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/wal/memtracker/PageMemoryTracker.java
@@ -32,6 +32,7 @@ import java.util.concurrent.locks.ReentrantLock;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.configuration.WALMode;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.mem.DirectMemoryProvider;
@@ -222,9 +223,21 @@ public class PageMemoryTracker implements IgnitePlugin {
pageSize = ctx.igniteConfiguration().getDataStorageConfiguration().getPageSize();
+ EncryptionSpi encSpi = ctx.igniteConfiguration().getEncryptionSpi();
+
pageMemoryMock = Mockito.mock(PageMemory.class);
Mockito.doReturn(pageSize).when(pageMemoryMock).pageSize();
+ Mockito.when(pageMemoryMock.realPageSize(Mockito.anyInt())).then(mock -> {
+ int grpId = (Integer) mock.getArguments()[0];
+
+ if (gridCtx.encryption().groupKey(grpId) == null)
+ return pageSize;
+
+ return pageSize
+ - (encSpi.encryptedSizeNoPadding(pageSize) - pageSize)
+ - encSpi.blockSize() /* For CRC. */;
+ });
GridCacheSharedContext sharedCtx = gridCtx.cache().context();
[5/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes
#4167.
Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateTxStateHintRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateTxStateHintRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateTxStateHintRecord.java
index 7e53609..fd77728 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateTxStateHintRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageMvccUpdateTxStateHintRecord.java
@@ -50,7 +50,7 @@ public class DataPageMvccUpdateTxStateHintRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
DataPageIO io = PageIO.getPageIO(pageAddr);
- io.updateTxState(pageAddr, itemId, pageMem.pageSize(), txState);
+ io.updateTxState(pageAddr, itemId, pageMem.realPageSize(groupId()), txState);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageRemoveRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageRemoveRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageRemoveRecord.java
index f7776be..abc84ea 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageRemoveRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageRemoveRecord.java
@@ -53,7 +53,7 @@ public class DataPageRemoveRecord extends PageDeltaRecord {
throws IgniteCheckedException {
AbstractDataPageIO io = PageIO.getPageIO(pageAddr);
- io.removeRow(pageAddr, itemId, pageMem.pageSize());
+ io.removeRow(pageAddr, itemId, pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageUpdateRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageUpdateRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageUpdateRecord.java
index ed469a4..6f5d8fd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageUpdateRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/DataPageUpdateRecord.java
@@ -71,7 +71,7 @@ public class DataPageUpdateRecord extends PageDeltaRecord {
AbstractDataPageIO io = PageIO.getPageIO(pageAddr);
- io.updateRow(pageAddr, itemId, pageMem.pageSize(), payload, null, 0);
+ io.updateRow(pageAddr, itemId, pageMem.realPageSize(groupId()), payload, null, 0);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/InitNewPageRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/InitNewPageRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/InitNewPageRecord.java
index c177a04..d0ba2aa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/InitNewPageRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/InitNewPageRecord.java
@@ -57,7 +57,7 @@ public class InitNewPageRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
PageIO io = PageIO.getPageIO(ioType, ioVer);
- io.initNewPage(pageAddr, newPageId, pageMem.pageSize());
+ io.initNewPage(pageAddr, newPageId, pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageAddRootRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageAddRootRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageAddRootRecord.java
index 4972155..9bf3aef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageAddRootRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageAddRootRecord.java
@@ -44,7 +44,7 @@ public class MetaPageAddRootRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
- io.addRoot(pageAddr, rootId, pageMem.pageSize());
+ io.addRoot(pageAddr, rootId, pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageCutRootRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageCutRootRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageCutRootRecord.java
index 5b896f6..1383a38 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageCutRootRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageCutRootRecord.java
@@ -38,7 +38,7 @@ public class MetaPageCutRootRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
- io.cutRoot(pageAddr, pageMem.pageSize());
+ io.cutRoot(pageAddr, pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
index ca995bf..7b3f3a9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRecord.java
@@ -76,7 +76,7 @@ public class MetaPageInitRecord extends InitNewPageRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
PageMetaIO io = PageMetaIO.getPageIO(ioType, ioVer);
- io.initNewPage(pageAddr, newPageId, pageMem.pageSize());
+ io.initNewPage(pageAddr, newPageId, pageMem.realPageSize(groupId()));
io.setTreeRoot(pageAddr, treeRoot);
io.setReuseListRoot(pageAddr, reuseListRoot);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java
index 0d3c155..71ae85d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootInlineRecord.java
@@ -51,7 +51,7 @@ public class MetaPageInitRootInlineRecord extends MetaPageInitRootRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
- io.initRoot(pageAddr, rootId, pageMem.pageSize());
+ io.initRoot(pageAddr, rootId, pageMem.realPageSize(groupId()));
io.setInlineSize(pageAddr, inlineSize);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
index 78a7e4f..7eca278 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/MetaPageInitRootRecord.java
@@ -44,7 +44,7 @@ public class MetaPageInitRootRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
BPlusMetaIO io = BPlusMetaIO.VERSIONS.forPage(pageAddr);
- io.initRoot(pageAddr, rootId, pageMem.pageSize());
+ io.initRoot(pageAddr, rootId, pageMem.realPageSize(groupId()));
io.setInlineSize(pageAddr, 0);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/NewRootInitRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/NewRootInitRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/NewRootInitRecord.java
index 4b8f747..1d78033 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/NewRootInitRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/NewRootInitRecord.java
@@ -71,7 +71,8 @@ public class NewRootInitRecord<L> extends PageDeltaRecord {
/** {@inheritDoc} */
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
- io.initNewRoot(pageAddr, newRootId, leftChildId, null, rowBytes, rightChildId, pageMem.pageSize(), false);
+ io.initNewRoot(pageAddr, newRootId, leftChildId, null, rowBytes, rightChildId, pageMem.realPageSize(groupId()),
+ false);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListAddPageRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListAddPageRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListAddPageRecord.java
index 6c7fc71..6f877b9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListAddPageRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListAddPageRecord.java
@@ -54,7 +54,7 @@ public class PagesListAddPageRecord extends PageDeltaRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
PagesListNodeIO io = PagesListNodeIO.VERSIONS.forPage(pageAddr);
- int cnt = io.addPage(pageAddr, dataPageId, pageMem.pageSize());
+ int cnt = io.addPage(pageAddr, dataPageId, pageMem.realPageSize(groupId()));
assert cnt >= 0 : cnt;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListInitNewPageRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListInitNewPageRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListInitNewPageRecord.java
index b2512aa..53c23b1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListInitNewPageRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/PagesListInitNewPageRecord.java
@@ -76,11 +76,11 @@ public class PagesListInitNewPageRecord extends InitNewPageRecord {
@Override public void applyDelta(PageMemory pageMem, long pageAddr) throws IgniteCheckedException {
PagesListNodeIO io = PageIO.getPageIO(PageIO.T_PAGE_LIST_NODE, ioVer);
- io.initNewPage(pageAddr, pageId(), pageMem.pageSize());
+ io.initNewPage(pageAddr, pageId(), pageMem.realPageSize(groupId()));
io.setPreviousId(pageAddr, prevPageId);
if (addDataPageId != 0L) {
- int cnt = io.addPage(pageAddr, addDataPageId, pageMem.pageSize());
+ int cnt = io.addPage(pageAddr, addDataPageId, pageMem.realPageSize(groupId()));
assert cnt == 0 : cnt;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/TrackingPageDeltaRecord.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/TrackingPageDeltaRecord.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/TrackingPageDeltaRecord.java
index 089eb9a..3f11c58 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/TrackingPageDeltaRecord.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/delta/TrackingPageDeltaRecord.java
@@ -76,7 +76,7 @@ public class TrackingPageDeltaRecord extends PageDeltaRecord {
pageIdToMark,
nextSnapshotId,
lastSuccessfulSnapshotId,
- pageMem.pageSize());
+ pageMem.realPageSize(groupId()));
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java
index ded37e7..d1598cd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/authentication/IgniteAuthenticationProcessor.java
@@ -97,9 +97,6 @@ public class IgniteAuthenticationProcessor extends GridProcessorAdapter implemen
/** Whan the future is done the node is ready for authentication. */
private final GridFutureAdapter<Void> readyForAuthFut = new GridFutureAdapter<>();
- /** Random is used to get random server node to authentication from client node. */
- private static final Random RND = new Random(System.currentTimeMillis());
-
/** Operation mutex. */
private final Object mux = new Object();
@@ -313,18 +310,7 @@ public class IgniteAuthenticationProcessor extends GridProcessorAdapter implemen
AuthenticateFuture fut;
synchronized (mux) {
- Collection<ClusterNode> aliveNodes = ctx.discovery().aliveServerNodes();
-
- int rndIdx = RND.nextInt(aliveNodes.size()) + 1;
-
- int i = 0;
- ClusterNode rndNode = null;
-
- for (Iterator<ClusterNode> it = aliveNodes.iterator(); i < rndIdx && it.hasNext(); i++)
- rndNode = it.next();
-
- if (rndNode == null)
- assert rndNode != null;
+ ClusterNode rndNode = U.randomServerNode(ctx);
fut = new AuthenticateFuture(rndNode.id());
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
index 8bed063..6ab4e67 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/ClusterCachesInfo.java
@@ -158,17 +158,6 @@ class ClusterCachesInfo {
}
/**
- * @param cacheName Cache name.
- * @param grpName Group name.
- * @return Group ID.
- */
- private int cacheGroupId(String cacheName, @Nullable String grpName) {
- assert cacheName != null;
-
- return grpName != null ? CU.cacheId(grpName) : CU.cacheId(cacheName);
- }
-
- /**
* @param checkConsistency {@code True} if need check cache configurations consistency.
* @throws IgniteCheckedException If failed.
*/
@@ -363,6 +352,9 @@ class ClusterCachesInfo {
"Query parallelism", locAttr.qryParallelism(), rmtAttr.qryParallelism(), true);
}
}
+
+ CU.checkAttributeMismatch(log, rmtAttr.cacheName(), rmt, "isEncryptionEnabled",
+ "Cache encrypted", locAttr.isEncryptionEnabled(), rmtAttr.isEncryptionEnabled(), true);
}
/**
@@ -574,7 +566,8 @@ class ClusterCachesInfo {
ccfg,
cacheId,
req.initiatingNodeId(),
- req.deploymentId());
+ req.deploymentId(),
+ req.encryptionKey());
DynamicCacheDescriptor startDesc = new DynamicCacheDescriptor(ctx,
ccfg,
@@ -1536,7 +1529,7 @@ class ClusterCachesInfo {
", conflictingCacheName=" + desc.cacheName() + ']';
}
- int grpId = cacheGroupId(cfg.getName(), cfg.getGroupName());
+ int grpId = CU.cacheGroupId(cfg.getName(), cfg.getGroupName());
if (cfg.getGroupName() != null) {
if (cacheGroupByName(cfg.getGroupName()) == null) {
@@ -1647,7 +1640,8 @@ class ClusterCachesInfo {
cfg,
cacheId,
nodeId,
- joinData.cacheDeploymentId());
+ joinData.cacheDeploymentId(),
+ null);
ctx.discovery().setCacheFilter(
cacheId,
@@ -1761,6 +1755,7 @@ class ClusterCachesInfo {
* @param cacheId Cache ID.
* @param rcvdFrom Node ID cache was recived from.
* @param deploymentId Deployment ID.
+ * @param encKey Encryption key.
* @return Group descriptor.
*/
private CacheGroupDescriptor registerCacheGroup(
@@ -1769,7 +1764,8 @@ class ClusterCachesInfo {
CacheConfiguration<?, ?> startedCacheCfg,
Integer cacheId,
UUID rcvdFrom,
- IgniteUuid deploymentId) {
+ IgniteUuid deploymentId,
+ @Nullable byte[] encKey) {
if (startedCacheCfg.getGroupName() != null) {
CacheGroupDescriptor desc = cacheGroupByName(startedCacheCfg.getGroupName());
@@ -1780,7 +1776,7 @@ class ClusterCachesInfo {
}
}
- int grpId = cacheGroupId(startedCacheCfg.getName(), startedCacheCfg.getGroupName());
+ int grpId = CU.cacheGroupId(startedCacheCfg.getName(), startedCacheCfg.getGroupName());
Map<String, Integer> caches = Collections.singletonMap(startedCacheCfg.getName(), cacheId);
@@ -1798,6 +1794,9 @@ class ClusterCachesInfo {
persistent,
null);
+ if (startedCacheCfg.isEncryptionEnabled())
+ ctx.encryption().beforeCacheGroupStart(grpId, encKey);
+
if (ctx.cache().context().pageStore() != null)
ctx.cache().context().pageStore().beforeCacheGroupStart(grpDesc);
@@ -1930,6 +1929,9 @@ class ClusterCachesInfo {
CU.validateCacheGroupsAttributesMismatch(log, cfg, startCfg, "backups", "Backups",
cfg.getBackups(), startCfg.getBackups(), true);
}
+
+ CU.validateCacheGroupsAttributesMismatch(log, cfg, startCfg, "encryptionEnabled", "Encrypted",
+ cfg.isEncryptionEnabled(), startCfg.isEncryptionEnabled(), true);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
index 2b942b0..5b8a89c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/DynamicCacheChangeRequest.java
@@ -95,6 +95,9 @@ public class DynamicCacheChangeRequest implements Serializable {
/** */
private transient boolean locallyConfigured;
+ /** Encryption key. */
+ @Nullable private byte[] encKey;
+
/**
* @param reqId Unique request ID.
* @param cacheName Cache stop name.
@@ -424,6 +427,20 @@ public class DynamicCacheChangeRequest implements Serializable {
this.disabledAfterStart = disabledAfterStart;
}
+ /**
+ * @param encKey Encryption key.
+ */
+ public void encryptionKey(@Nullable byte[] encKey) {
+ this.encKey = encKey;
+ }
+
+ /**
+ * @return Encryption key.
+ */
+ @Nullable public byte[] encryptionKey() {
+ return encKey;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return "DynamicCacheChangeRequest [cacheName=" + cacheName() +
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
index 01daee2..230320a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAttributes.java
@@ -353,6 +353,13 @@ public class GridCacheAttributes implements Serializable {
}
/**
+ * @return Is cache encryption enabled.
+ */
+ public boolean isEncryptionEnabled() {
+ return ccfg.isEncryptionEnabled();
+ }
+
+ /**
* @param obj Object to get class of.
* @return Class name or {@code null}.
*/
@@ -364,4 +371,4 @@ public class GridCacheAttributes implements Serializable {
@Override public String toString() {
return S.toString(GridCacheAttributes.class, this);
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index 16e1799..f595ecf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -25,6 +25,7 @@ import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -61,6 +62,7 @@ import org.apache.ignite.configuration.MemoryConfiguration;
import org.apache.ignite.configuration.NearCacheConfiguration;
import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.configuration.WALMode;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.events.EventType;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
@@ -136,6 +138,7 @@ import org.apache.ignite.internal.util.F0;
import org.apache.ignite.internal.util.future.GridCompoundFuture;
import org.apache.ignite.internal.util.future.GridFinishedFuture;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.apache.ignite.internal.util.lang.GridPlainClosure;
import org.apache.ignite.internal.util.lang.IgniteOutClosureX;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.CIX1;
@@ -149,6 +152,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgniteClosure;
import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.lang.IgnitePredicate;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.lifecycle.LifecycleAware;
@@ -598,6 +602,22 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
}
}
}
+
+ if (cc.isEncryptionEnabled() && !ctx.clientNode()) {
+ if (!CU.isPersistentCache(cc, c.getDataStorageConfiguration())) {
+ throw new IgniteCheckedException("Using encryption is not allowed" +
+ " for not persistent cache [cacheName=" + cc.getName() + ", groupName=" + cc.getGroupName() +
+ ", cacheType=" + cacheType + "]");
+ }
+
+ EncryptionSpi encSpi = c.getEncryptionSpi();
+
+ if (encSpi == null) {
+ throw new IgniteCheckedException("EncryptionSpi should be configured to use encrypted cache " +
+ "[cacheName=" + cc.getName() + ", groupName=" + cc.getGroupName() +
+ ", cacheType=" + cacheType + "]");
+ }
+ }
}
/**
@@ -903,6 +923,15 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
", configuredAtomicityMode=" + cfg.getAtomicityMode() +
", storedAtomicityMode=" + cfgFromStore.getAtomicityMode() + "]");
}
+
+ boolean staticCfgVal = cfg.isEncryptionEnabled();
+
+ boolean storedVal = cfgFromStore.isEncryptionEnabled();
+
+ if (storedVal != staticCfgVal) {
+ throw new IgniteCheckedException("Encrypted flag value differs. Static config value is '" + staticCfgVal +
+ "' and value stored on the disk is '" + storedVal + "'");
+ }
}
/**
@@ -1311,7 +1340,8 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
", mode=" + cfg.getCacheMode() +
", atomicity=" + cfg.getAtomicityMode() +
", backups=" + cfg.getBackups() +
- ", mvcc=" + cacheCtx.mvccEnabled() +']');
+ ", mvcc=" + cacheCtx.mvccEnabled() +']' +
+ ", encryptionEnabled=" + cfg.isEncryptionEnabled() +']');
}
}
@@ -3107,7 +3137,9 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
if (checkThreadTx)
checkEmptyTransactions();
- try {
+ GridPlainClosure<Collection<byte[]>, IgniteInternalFuture<Boolean>> startCacheClsr = (grpKeys) -> {
+ assert ccfg == null || !ccfg.isEncryptionEnabled() || !grpKeys.isEmpty();
+
DynamicCacheChangeRequest req = prepareCacheChangeRequest(
ccfg,
cacheName,
@@ -3117,7 +3149,8 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
failIfExists,
failIfNotStarted,
false,
- null);
+ null,
+ ccfg != null && ccfg.isEncryptionEnabled() ? grpKeys.iterator().next() : null);
if (req != null) {
if (req.clientStartOnly())
@@ -3127,6 +3160,16 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
}
else
return new GridFinishedFuture<>();
+ };
+
+ try {
+ if (ccfg != null && ccfg.isEncryptionEnabled()) {
+ ctx.encryption().checkEncryptedCacheSupported();
+
+ return generateEncryptionKeysAndStartCacheAfter(1, startCacheClsr);
+ }
+
+ return startCacheClsr.apply(Collections.EMPTY_SET);
}
catch (Exception e) {
return new GridFinishedFuture<>(e);
@@ -3134,6 +3177,48 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
}
/**
+ * Send {@code GenerateEncryptionKeyRequest} and execute {@code after} closure if succeed.
+ *
+ * @param keyCnt Count of keys to generate.
+ * @param after Closure to execute after encryption keys would be generated.
+ */
+ private IgniteInternalFuture<Boolean> generateEncryptionKeysAndStartCacheAfter(int keyCnt,
+ GridPlainClosure<Collection<byte[]>, IgniteInternalFuture<Boolean>> after) {
+ IgniteInternalFuture<Collection<byte[]>> genEncKeyFut = ctx.encryption().generateKeys(keyCnt);
+
+ GridFutureAdapter<Boolean> res = new GridFutureAdapter<>();
+
+ genEncKeyFut.listen(new IgniteInClosure<IgniteInternalFuture<Collection<byte[]>>>() {
+ @Override public void apply(IgniteInternalFuture<Collection<byte[]>> fut) {
+ try {
+ Collection<byte[]> grpKeys = fut.result();
+
+ if (F.size(grpKeys, F.alwaysTrue()) != keyCnt)
+ res.onDone(false, fut.error());
+
+ IgniteInternalFuture<Boolean> dynStartCacheFut = after.apply(grpKeys);
+
+ dynStartCacheFut.listen(new IgniteInClosure<IgniteInternalFuture<Boolean>>() {
+ @Override public void apply(IgniteInternalFuture<Boolean> fut) {
+ try {
+ res.onDone(fut.get(), fut.error());
+ }
+ catch (IgniteCheckedException e) {
+ res.onDone(false, e);
+ }
+ }
+ });
+ }
+ catch (Exception e) {
+ res.onDone(false, e);
+ }
+ }
+ });
+
+ return res;
+ }
+
+ /**
* @param startReqs Start requests.
* @param cachesToClose Cache tp close.
* @return Future for cache change operation.
@@ -3167,7 +3252,7 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
* @param disabledAfterStart If true, cache proxies will be only activated after {@link #restartProxies()}.
* @return Future that will be completed when all caches are deployed.
*/
- public IgniteInternalFuture<?> dynamicStartCaches(Collection<CacheConfiguration> ccfgList, boolean failIfExists,
+ public IgniteInternalFuture<Boolean> dynamicStartCaches(Collection<CacheConfiguration> ccfgList, boolean failIfExists,
boolean checkThreadTx, boolean disabledAfterStart) {
return dynamicStartCachesByStoredConf(
ccfgList.stream().map(StoredCacheData::new).collect(Collectors.toList()),
@@ -3186,7 +3271,7 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
* @param disabledAfterStart If true, cache proxies will be only activated after {@link #restartProxies()}.
* @return Future that will be completed when all caches are deployed.
*/
- public IgniteInternalFuture<?> dynamicStartCachesByStoredConf(
+ public IgniteInternalFuture<Boolean> dynamicStartCachesByStoredConf(
Collection<StoredCacheData> storedCacheDataList,
boolean failIfExists,
boolean checkThreadTx,
@@ -3194,11 +3279,15 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
if (checkThreadTx)
checkEmptyTransactions();
- List<DynamicCacheChangeRequest> srvReqs = null;
- Map<String, DynamicCacheChangeRequest> clientReqs = null;
+ GridPlainClosure<Collection<byte[]>, IgniteInternalFuture<Boolean>> startCacheClsr = (grpKeys) -> {
+ List<DynamicCacheChangeRequest> srvReqs = null;
+ Map<String, DynamicCacheChangeRequest> clientReqs = null;
+
+ Iterator<byte[]> grpKeysIter = grpKeys.iterator();
- try {
for (StoredCacheData ccfg : storedCacheDataList) {
+ assert !ccfg.config().isEncryptionEnabled() || grpKeysIter.hasNext();
+
DynamicCacheChangeRequest req = prepareCacheChangeRequest(
ccfg.config(),
ccfg.config().getName(),
@@ -3208,7 +3297,8 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
failIfExists,
true,
disabledAfterStart,
- ccfg.queryEntities());
+ ccfg.queryEntities(),
+ ccfg.config().isEncryptionEnabled() ? grpKeysIter.next() : null);
if (req != null) {
if (req.clientStartOnly()) {
@@ -3225,16 +3315,14 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
}
}
}
- }
- catch (Exception e) {
- return new GridFinishedFuture<>(e);
- }
- if (srvReqs != null || clientReqs != null) {
+ if (srvReqs == null && clientReqs == null)
+ return new GridFinishedFuture<>();
+
if (clientReqs != null && srvReqs == null)
return startClientCacheChange(clientReqs, null);
- GridCompoundFuture<?, ?> compoundFut = new GridCompoundFuture<>();
+ GridCompoundFuture<?, Boolean> compoundFut = new GridCompoundFuture<>();
for (DynamicCacheStartFuture fut : initiateCacheChanges(srvReqs))
compoundFut.add((IgniteInternalFuture)fut);
@@ -3248,9 +3336,16 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
compoundFut.markInitialized();
return compoundFut;
+ };
+
+ int encGrpCnt = 0;
+
+ for (StoredCacheData ccfg : storedCacheDataList) {
+ if (ccfg.config().isEncryptionEnabled())
+ encGrpCnt++;
}
- else
- return new GridFinishedFuture<>();
+
+ return generateEncryptionKeysAndStartCacheAfter(encGrpCnt, startCacheClsr);
}
/** Resolve cache type for input cacheType */
@@ -4539,6 +4634,7 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
* @param failIfNotStarted If {@code true} fails if cache is not started.
* @param disabledAfterStart If true, cache proxies will be only activated after {@link #restartProxies()}.
* @param qryEntities Query entities.
+ * @param encKey Encryption key.
* @return Request or {@code null} if cache already exists.
* @throws IgniteCheckedException if some of pre-checks failed
* @throws CacheExistsException if cache exists and failIfExists flag is {@code true}
@@ -4552,7 +4648,8 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
boolean failIfExists,
boolean failIfNotStarted,
boolean disabledAfterStart,
- @Nullable Collection<QueryEntity> qryEntities
+ @Nullable Collection<QueryEntity> qryEntities,
+ @Nullable byte[] encKey
) throws IgniteCheckedException {
DynamicCacheDescriptor desc = cacheDescriptor(cacheName);
@@ -4564,6 +4661,8 @@ public class GridCacheProcessor extends GridProcessorAdapter implements Metastor
req.disabledAfterStart(disabledAfterStart);
+ req.encryptionKey(encKey);
+
if (ccfg != null) {
cloneCheckSerializable(ccfg);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
index 91a449f..c316621 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
@@ -58,6 +58,7 @@ import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.TransactionConfiguration;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
import org.apache.ignite.internal.IgniteInternalFuture;
@@ -1149,6 +1150,17 @@ public class GridCacheUtils {
}
/**
+ * @param cacheName Cache name.
+ * @param grpName Group name.
+ * @return Group ID.
+ */
+ public static int cacheGroupId(String cacheName, @Nullable String grpName) {
+ assert cacheName != null;
+
+ return grpName != null ? CU.cacheId(grpName) : CU.cacheId(cacheName);
+ }
+
+ /**
* @param cfg Grid configuration.
* @param cacheName Cache name.
* @return {@code True} in this is IGFS data or meta cache.
@@ -1900,6 +1912,17 @@ public class GridCacheUtils {
}
/**
+ * @param pageSize Page size.
+ * @param encSpi Encryption spi.
+ * @return Page size without encryption overhead.
+ */
+ public static int encryptedPageSize(int pageSize, EncryptionSpi encSpi) {
+ return pageSize
+ - (encSpi.encryptedSizeNoPadding(pageSize) - pageSize)
+ - encSpi.blockSize(); /* For CRC. */
+ }
+
+ /**
* @param sctx Shared context.
* @param cacheIds Cache ids.
* @return First partitioned cache or {@code null} in case no partitioned cache ids are in list.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index a968737..0182c8a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -3139,7 +3139,8 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
DataPageIO iox = (DataPageIO)io;
- int offset = iox.getPayloadOffset(pageAddr, itemId, grp.dataRegion().pageMemory().pageSize(), MVCC_INFO_SIZE);
+ int offset = iox.getPayloadOffset(pageAddr, itemId,
+ grp.dataRegion().pageMemory().realPageSize(grp.groupId()), MVCC_INFO_SIZE);
long newCrd = iox.newMvccCoordinator(pageAddr, offset);
long newCntr = iox.newMvccCounter(pageAddr, offset);
@@ -3168,8 +3169,8 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
DataPageIO iox = (DataPageIO)io;
- int pageSize = grp.dataRegion().pageMemory().pageSize();
- int offset = iox.getPayloadOffset(pageAddr, itemId, pageSize, MVCC_INFO_SIZE);
+ int offset = iox.getPayloadOffset(pageAddr, itemId,
+ grp.dataRegion().pageMemory().realPageSize(grp.groupId()), MVCC_INFO_SIZE);
long crd = iox.mvccCoordinator(pageAddr, offset);
long cntr = iox.mvccCounter(pageAddr, offset);
@@ -3222,7 +3223,8 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
DataPageIO iox = (DataPageIO)io;
- int offset = iox.getPayloadOffset(pageAddr, itemId, grp.dataRegion().pageMemory().pageSize(), MVCC_INFO_SIZE);
+ int offset = iox.getPayloadOffset(pageAddr, itemId,
+ grp.dataRegion().pageMemory().realPageSize(grp.groupId()), MVCC_INFO_SIZE);
long crd = iox.mvccCoordinator(pageAddr, offset);
long cntr = iox.mvccCounter(pageAddr, offset);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
index f43afa0..2052c36 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
@@ -1052,6 +1052,8 @@ public class GridDhtPartitionsExchangeFuture extends GridDhtTopologyFutureAdapte
registerCachesFuture = cctx.affinity().onCacheChangeRequest(this, crd, exchActions);
+ cctx.kernalContext().encryption().onDeActivate(cctx.kernalContext());
+
if (log.isInfoEnabled()) {
log.info("Successfully deactivated data structures, services and caches [" +
"nodeId=" + cctx.localNodeId() +
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
index 896c9aa..a659245 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/mvcc/MvccUtils.java
@@ -577,7 +577,8 @@ public class MvccUtils {
try{
DataPageIO dataIo = DataPageIO.VERSIONS.forPage(pageAddr);
- int offset = dataIo.getPayloadOffset(pageAddr, itemId(link), pageMem.pageSize(), MVCC_INFO_SIZE);
+ int offset = dataIo.getPayloadOffset(pageAddr, itemId(link), pageMem.realPageSize(grpId),
+ MVCC_INFO_SIZE);
long mvccCrd = dataIo.mvccCoordinator(pageAddr, offset);
long mvccCntr = dataIo.mvccCounter(pageAddr, offset);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
index 574e6d5..8b44ff6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/CacheDataRowAdapter.java
@@ -155,7 +155,7 @@ public class CacheDataRowAdapter implements CacheDataRow {
DataPagePayload data = io.readPayload(pageAddr,
itemId(nextLink),
- pageMem.pageSize());
+ pageMem.realPageSize(grpId));
nextLink = data.nextLink();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
index 0177407..c23a970 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStructure.java
@@ -387,10 +387,10 @@ public abstract class DataStructure implements PageLockListener {
}
/**
- * @return Page size.
+ * @return Page size without encryption overhead.
*/
- protected final int pageSize() {
- return pageMem.pageSize();
+ protected int pageSize() {
+ return pageMem.realPageSize(grpId);
}
@Override public void onBeforeWriteLock(int cacheId, long pageId, long page) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
index 1d048c0..e4a385f 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java
@@ -1430,6 +1430,9 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan
grpIds.add(tup.get1().groupId());
pageMem.onCacheGroupDestroyed(tup.get1().groupId());
+
+ if (tup.get2())
+ cctx.kernalContext().encryption().onCacheGroupDestroyed(gctx.groupId());
}
Collection<IgniteInternalFuture<Void>> clearFuts = new ArrayList<>(destroyed.size());
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
index 801703b..c6f8415 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java
@@ -482,8 +482,6 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
try {
final long curAddr = pageMem.writeLock(grpId, curId, curPage);
- int pageSize = pageMem.pageSize();
-
assert curAddr != 0;
try {
@@ -492,12 +490,12 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
if (init) {
partCntrIo = PagePartitionCountersIO.VERSIONS.latest();
- partCntrIo.initNewPage(curAddr, curId, pageSize);
+ partCntrIo.initNewPage(curAddr, curId, pageMem.realPageSize(grpId));
}
else
partCntrIo = PageIO.getPageIO(curAddr);
- written += partCntrIo.writeCacheSizes(pageSize, curAddr, data, written);
+ written += partCntrIo.writeCacheSizes(pageMem.realPageSize(grpId), curAddr, data, written);
nextId = partCntrIo.getNextCountersPageId(curAddr);
@@ -727,7 +725,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
if (PageIO.getType(pageAddr) != PageIO.T_META) {
PageMetaIO pageIO = PageMetaIO.VERSIONS.latest();
- pageIO.initNewPage(pageAddr, metaId, pageMem.pageSize());
+ pageIO.initNewPage(pageAddr, metaId, pageMem.realPageSize(grpId));
metastoreRoot = pageMem.allocatePage(grpId, PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX);
reuseListRoot = pageMem.allocatePage(grpId, PageIdAllocator.INDEX_PARTITION, PageMemory.FLAG_IDX);
@@ -1464,7 +1462,7 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
if (PageIO.getType(pageAddr) != PageIO.T_PART_META) {
PagePartitionMetaIO io = PagePartitionMetaIO.VERSIONS.latest();
- io.initNewPage(pageAddr, partMetaId, pageMem.pageSize());
+ io.initNewPage(pageAddr, partMetaId, pageMem.realPageSize(grpId));
treeRoot = pageMem.allocatePage(grpId, partId, PageMemory.FLAG_DATA);
reuseListRoot = pageMem.allocatePage(grpId, partId, PageMemory.FLAG_DATA);
@@ -1478,8 +1476,10 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
io.setReuseListRoot(pageAddr, reuseListRoot);
io.setPendingTreeRoot(pageAddr, pendingTreeRoot);
- if (PageHandler.isWalDeltaRecordNeeded(pageMem, grpId, partMetaId, partMetaPage, wal, null))
- wal.log(new PageSnapshot(new FullPageId(partMetaId, grpId), pageAddr, pageMem.pageSize()));
+ if (PageHandler.isWalDeltaRecordNeeded(pageMem, grpId, partMetaId, partMetaPage, wal, null)) {
+ wal.log(new PageSnapshot(new FullPageId(partMetaId, grpId), pageAddr,
+ pageMem.pageSize(), pageMem.realPageSize(grpId)));
+ }
allocated = true;
}
@@ -1508,8 +1508,11 @@ public class GridCacheOffheapManager extends IgniteCacheOffheapManagerImpl imple
io.setPendingTreeRoot(pageAddr, pendingTreeRoot);
- if (PageHandler.isWalDeltaRecordNeeded(pageMem, grpId, partMetaId, partMetaPage, wal, null))
- wal.log(new PageSnapshot(new FullPageId(partMetaId, grpId), pageAddr, pageMem.pageSize()));
+ if (PageHandler.isWalDeltaRecordNeeded(pageMem, grpId, partMetaId, partMetaPage, wal,
+ null)) {
+ wal.log(new PageSnapshot(new FullPageId(partMetaId, grpId), pageAddr,
+ pageMem.pageSize(), pageMem.realPageSize(grpId)));
+ }
pendingTreeAllocated = true;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIO.java
new file mode 100644
index 0000000..008a728
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIO.java
@@ -0,0 +1,371 @@
+/*
+ * 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.ignite.internal.processors.cache.persistence.file;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
+import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
+import org.apache.ignite.internal.processors.cache.persistence.wal.crc.PureJavaCrc32;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+
+/**
+ * Implementation of {@code FileIO} that supports encryption(decryption) of pages written(readed) to(from) file.
+ *
+ * @see EncryptedFileIOFactory
+ */
+public class EncryptedFileIO implements FileIO {
+ /**
+ * Underlying file.
+ */
+ private final FileIO plainFileIO;
+
+ /**
+ * Group id.
+ */
+ private final int groupId;
+
+ /**
+ * Size of plain data page in bytes.
+ */
+ private final int pageSize;
+
+ /**
+ * Size of file header in bytes.
+ */
+ private final int headerSize;
+
+ /**
+ * Shared database manager.
+ */
+ private final GridEncryptionManager encMgr;
+
+ /**
+ * Shared database manager.
+ */
+ private final EncryptionSpi encSpi;
+
+ /**
+ * Encryption key.
+ */
+ private Serializable encKey;
+
+ /**
+ * Extra bytes added by encryption.
+ */
+ private final int encryptionOverhead;
+
+ /**
+ * Array of zeroes to fulfill tail of decrypted page.
+ */
+ private final byte[] zeroes;
+
+ /**
+ * @param plainFileIO Underlying file.
+ * @param groupId Group id.
+ * @param pageSize Size of plain data page in bytes.
+ * @param headerSize Size of file header in bytes.
+ * @param encMgr Encryption manager.
+ */
+ EncryptedFileIO(FileIO plainFileIO, int groupId, int pageSize, int headerSize,
+ GridEncryptionManager encMgr, EncryptionSpi encSpi) {
+ this.plainFileIO = plainFileIO;
+ this.groupId = groupId;
+ this.pageSize = pageSize;
+ this.headerSize = headerSize;
+ this.encMgr = encMgr;
+ this.encSpi = encSpi;
+
+ this.encryptionOverhead = pageSize - CU.encryptedPageSize(pageSize, encSpi);
+ this.zeroes = new byte[encryptionOverhead];
+ }
+
+ /** {@inheritDoc} */
+ @Override public long position() throws IOException {
+ return plainFileIO.position();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void position(long newPosition) throws IOException {
+ plainFileIO.position(newPosition);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int read(ByteBuffer destBuf) throws IOException {
+ assert position() == 0;
+
+ return plainFileIO.read(destBuf);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int readFully(ByteBuffer destBuf) throws IOException {
+ return read(destBuf);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int read(ByteBuffer destBuf, long position) throws IOException {
+ assert destBuf.remaining() >= pageSize;
+ assert position() != 0;
+
+ ByteBuffer encrypted = ByteBuffer.allocate(pageSize);
+
+ int res = plainFileIO.read(encrypted, position);
+
+ if (res < 0)
+ return res;
+
+ if (res != pageSize) {
+ throw new IllegalStateException("Expecting to read whole page[" + pageSize + " bytes], " +
+ "but read only " + res + " bytes");
+ }
+
+ encrypted.rewind();
+
+ decrypt(encrypted, destBuf);
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int readFully(ByteBuffer destBuf, long position) throws IOException {
+ assert destBuf.capacity() == pageSize;
+ assert position() != 0;
+
+ ByteBuffer encrypted = ByteBuffer.allocate(pageSize);
+
+ int res = plainFileIO.readFully(encrypted, position);
+
+ if (res < 0)
+ return res;
+
+ if (res != pageSize) {
+ throw new IllegalStateException("Expecting to read whole page[" + pageSize + " bytes], " +
+ "but read only " + res + " bytes");
+ }
+
+ encrypted.rewind();
+
+ decrypt(encrypted, destBuf);
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int read(byte[] buf, int off, int len) throws IOException {
+ throw new UnsupportedOperationException("Encrypted File doesn't support this operation");
+ }
+
+ /** {@inheritDoc} */
+ @Override public int readFully(byte[] buf, int off, int len) throws IOException {
+ return read(buf, off, len);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int write(ByteBuffer srcBuf) throws IOException {
+ assert position() == 0;
+ assert headerSize == srcBuf.capacity();
+
+ return plainFileIO.write(srcBuf);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int writeFully(ByteBuffer srcBuf) throws IOException {
+ return write(srcBuf);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int write(ByteBuffer srcBuf, long position) throws IOException {
+ ByteBuffer encrypted = ByteBuffer.allocate(pageSize);
+
+ encrypt(srcBuf, encrypted);
+
+ encrypted.rewind();
+
+ return plainFileIO.write(encrypted, position);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int writeFully(ByteBuffer srcBuf, long position) throws IOException {
+ ByteBuffer encrypted = ByteBuffer.allocate(pageSize);
+
+ encrypt(srcBuf, encrypted);
+
+ encrypted.rewind();
+
+ return plainFileIO.writeFully(encrypted, position);
+ }
+
+ /**
+ * @param srcBuf Source buffer.
+ * @param res Destination buffer.
+ * @throws IOException If failed.
+ */
+ private void encrypt(ByteBuffer srcBuf, ByteBuffer res) throws IOException {
+ assert position() != 0;
+ assert srcBuf.remaining() >= pageSize;
+ assert tailIsEmpty(srcBuf, PageIO.getType(srcBuf));
+
+ int srcLimit = srcBuf.limit();
+
+ srcBuf.limit(srcBuf.position() + plainDataSize());
+
+ encSpi.encryptNoPadding(srcBuf, key(), res);
+
+ res.rewind();
+
+ storeCRC(res);
+
+ srcBuf.limit(srcLimit);
+ srcBuf.position(srcBuf.position() + encryptionOverhead);
+ }
+
+ /**
+ * @param encrypted Encrypted buffer.
+ * @param destBuf Destination buffer.
+ */
+ private void decrypt(ByteBuffer encrypted, ByteBuffer destBuf) throws IOException {
+ assert encrypted.remaining() >= pageSize;
+ assert encrypted.limit() >= pageSize;
+
+ checkCRC(encrypted);
+
+ encrypted.limit(encryptedDataSize());
+
+ encSpi.decryptNoPadding(encrypted, key(), destBuf);
+
+ destBuf.put(zeroes); //Forcibly purge page buffer tail.
+ }
+
+ /**
+ * Stores CRC in res.
+ *
+ * @param res Destination buffer.
+ */
+ private void storeCRC(ByteBuffer res) {
+ int crc = PureJavaCrc32.calcCrc32(res, encryptedDataSize());
+
+ res.put((byte) (crc >> 24));
+ res.put((byte) (crc >> 16));
+ res.put((byte) (crc >> 8));
+ res.put((byte) crc);
+ }
+
+ /**
+ * Checks encrypted data integrity.
+ *
+ * @param encrypted Encrypted data buffer.
+ */
+ private void checkCRC(ByteBuffer encrypted) throws IOException {
+ int crc = PureJavaCrc32.calcCrc32(encrypted, encryptedDataSize());
+
+ int storedCrc = 0;
+
+ storedCrc |= (int)encrypted.get() << 24;
+ storedCrc |= ((int)encrypted.get() & 0xff) << 16;
+ storedCrc |= ((int)encrypted.get() & 0xff) << 8;
+ storedCrc |= encrypted.get() & 0xff;
+
+ if(crc != storedCrc) {
+ throw new IOException("Content of encrypted page is broken. [StoredCrc=" + storedCrc +
+ ", calculatedCrd=" + crc + "]");
+ }
+
+ encrypted.position(encrypted.position() - (encryptedDataSize() + 4 /* CRC size. */));
+ }
+
+ /**
+ * @return Encrypted data size.
+ */
+ private int encryptedDataSize() {
+ return pageSize - encSpi.blockSize();
+ }
+
+ /**
+ * @return Plain data size.
+ */
+ private int plainDataSize() {
+ return pageSize - encryptionOverhead;
+ }
+
+ /** */
+ private boolean tailIsEmpty(ByteBuffer src, int pageType) {
+ int srcPos = src.position();
+
+ src.position(srcPos + plainDataSize());
+
+ for (int i = 0; i < encryptionOverhead; i++)
+ assert src.get() == 0 : "Tail of src should be empty [i=" + i + ", pageType=" + pageType + "]";
+
+ src.position(srcPos);
+
+ return true;
+ }
+
+ /**
+ * @return Encryption key.
+ */
+ private Serializable key() {
+ if (encKey == null)
+ return encKey = encMgr.groupKey(groupId);
+
+ return encKey;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int write(byte[] buf, int off, int len) throws IOException {
+ throw new UnsupportedOperationException("Encrypted File doesn't support this operation");
+ }
+
+ /** {@inheritDoc} */
+ @Override public int writeFully(byte[] buf, int off, int len) throws IOException {
+ return write(buf, off, len);
+ }
+
+ /** {@inheritDoc} */
+ @Override public MappedByteBuffer map(int sizeBytes) throws IOException {
+ throw new UnsupportedOperationException("Encrypted File doesn't support this operation");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void force() throws IOException {
+ plainFileIO.force();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void force(boolean withMetadata) throws IOException {
+ plainFileIO.force(withMetadata);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long size() throws IOException {
+ return plainFileIO.size();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void clear() throws IOException {
+ plainFileIO.clear();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close() throws IOException {
+ plainFileIO.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIOFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIOFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIOFactory.java
new file mode 100644
index 0000000..336aab6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/EncryptedFileIOFactory.java
@@ -0,0 +1,100 @@
+/*
+ * 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.ignite.internal.processors.cache.persistence.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.OpenOption;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
+
+/**
+ * Factory to produce {@code EncryptedFileIO}.
+ */
+public class EncryptedFileIOFactory implements FileIOFactory {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * Factory to produce underlying {@code FileIO} instances.
+ */
+ private FileIOFactory plainIOFactory;
+
+ /**
+ * Size of plain data page in bytes.
+ */
+ private int pageSize;
+
+ /**
+ * Size of file header in bytes.
+ */
+ private int headerSize;
+
+ /**
+ * Group id.
+ */
+ private int groupId;
+
+ /**
+ * Encryption manager.
+ */
+ private GridEncryptionManager encMgr;
+
+ /**
+ * Encryption spi.
+ */
+ private EncryptionSpi encSpi;
+
+ /**
+ * @param plainIOFactory Underlying file factory.
+ * @param groupId Group id.
+ * @param pageSize Size of plain data page in bytes.
+ * @param encMgr Encryption manager.
+ */
+ EncryptedFileIOFactory(FileIOFactory plainIOFactory, int groupId, int pageSize, GridEncryptionManager encMgr,
+ EncryptionSpi encSpi) {
+ this.plainIOFactory = plainIOFactory;
+ this.groupId = groupId;
+ this.pageSize = pageSize;
+ this.encMgr = encMgr;
+ this.encSpi = encSpi;
+ }
+
+ /** {@inheritDoc} */
+ @Override public FileIO create(File file) throws IOException {
+ FileIO io = plainIOFactory.create(file);
+
+ return new EncryptedFileIO(io, groupId, pageSize, headerSize, encMgr, encSpi);
+ }
+
+ /** {@inheritDoc} */
+ @Override public FileIO create(File file, OpenOption... modes) throws IOException {
+ FileIO io = plainIOFactory.create(file, modes);
+
+ return new EncryptedFileIO(io, groupId, pageSize, headerSize, encMgr, encSpi);
+ }
+
+ /**
+ * Sets size of file header in bytes.
+ *
+ * @param headerSize Size of file header in bytes.
+ */
+ void headerSize(int headerSize) {
+ this.headerSize = headerSize;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
index 110807c..2e07867 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java
@@ -235,11 +235,8 @@ public class FilePageStore implements PageStore {
return fileSize;
}
- /**
- * @param delete {@code True} to delete file.
- * @throws StorageException If failed in case of underlying I/O exception.
- */
- public void stop(boolean delete) throws StorageException {
+ /** {@inheritDoc} */
+ @Override public void stop(boolean delete) throws StorageException {
lock.writeLock().lock();
try {
@@ -264,13 +261,8 @@ public class FilePageStore implements PageStore {
}
}
- /**
- * Truncates and deletes partition file.
- *
- * @param tag New partition tag.
- * @throws StorageException If failed in case of underlying I/O exception.
- */
- public void truncate(int tag) throws StorageException {
+ /** {@inheritDoc} */
+ @Override public void truncate(int tag) throws StorageException {
init();
lock.writeLock().lock();
@@ -298,10 +290,8 @@ public class FilePageStore implements PageStore {
}
}
- /**
- *
- */
- public void beginRecover() {
+ /** {@inheritDoc} */
+ @Override public void beginRecover() {
lock.writeLock().lock();
try {
@@ -312,10 +302,8 @@ public class FilePageStore implements PageStore {
}
}
- /**
- * @throws StorageException If failed in case of underlying I/O exception.
- */
- public void finishRecover() throws StorageException {
+ /** {@inheritDoc} */
+ @Override public void finishRecover() throws StorageException {
lock.writeLock().lock();
try {
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
index fe93d07..2fb1d50 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreFactory.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache.persistence.file;
import java.io.File;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.pagemem.PageIdAllocator;
+import org.apache.ignite.internal.pagemem.store.PageStore;
import org.apache.ignite.internal.processors.cache.persistence.AllocatedPageTracker;
/**
@@ -32,5 +33,5 @@ public interface FilePageStoreFactory {
* @param type Data type, can be {@link PageIdAllocator#FLAG_IDX} or {@link PageIdAllocator#FLAG_DATA}.
* @param file File Page store file.
*/
- public FilePageStore createPageStore(byte type, File file, AllocatedPageTracker allocatedTracker) throws IgniteCheckedException;
+ PageStore createPageStore(byte type, File file, AllocatedPageTracker allocatedTracker) throws IgniteCheckedException;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
index 101a33d..c6cd9e5 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java
@@ -262,7 +262,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
for (CacheStoreHolder holder : idxCacheStores.values()) {
holder.idxStore.beginRecover();
- for (FilePageStore partStore : holder.partStores)
+ for (PageStore partStore : holder.partStores)
partStore.beginRecover();
}
}
@@ -273,7 +273,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
for (CacheStoreHolder holder : idxCacheStores.values()) {
holder.idxStore.finishRecover();
- for (FilePageStore partStore : holder.partStores)
+ for (PageStore partStore : holder.partStores)
partStore.finishRecover();
}
}
@@ -292,7 +292,8 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
new File(storeWorkDir, workingDir),
cacheId,
partitions,
- tracker
+ tracker,
+ cctx.cacheContext(cacheId) != null && cctx.cacheContext(cacheId).config().isEncryptionEnabled()
);
CacheStoreHolder old = idxCacheStores.put(cacheId, holder);
@@ -321,9 +322,10 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
if (!idxCacheStores.containsKey(grpId)) {
CacheStoreHolder holder = initDir(
new File(storeWorkDir, META_STORAGE_NAME),
- grpId,
- 1,
- AllocatedPageTracker.NO_OP );
+ grpId,
+ 1,
+ AllocatedPageTracker.NO_OP,
+ false);
CacheStoreHolder old = idxCacheStores.put(grpId, holder);
@@ -400,9 +402,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
PageStore store = getStore(grpId, partId);
- assert store instanceof FilePageStore : store;
-
- ((FilePageStore)store).truncate(tag);
+ store.truncate(tag);
}
/** {@inheritDoc} */
@@ -521,7 +521,8 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
cacheWorkDir,
grpDesc.groupId(),
grpDesc.config().getAffinity().partitions(),
- allocatedTracker
+ allocatedTracker,
+ ccfg.isEncryptionEnabled()
);
}
@@ -530,13 +531,15 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
* @param grpId Group ID.
* @param partitions Number of partitions.
* @param allocatedTracker Metrics updater.
+ * @param encrypted {@code True} if this cache encrypted.
* @return Cache store holder.
* @throws IgniteCheckedException If failed.
*/
private CacheStoreHolder initDir(File cacheWorkDir,
int grpId,
int partitions,
- AllocatedPageTracker allocatedTracker) throws IgniteCheckedException {
+ AllocatedPageTracker allocatedTracker,
+ boolean encrypted) throws IgniteCheckedException {
try {
boolean dirExisted = checkAndInitCacheWorkDir(cacheWorkDir);
@@ -545,19 +548,48 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
if (dirExisted && !idxFile.exists())
grpsWithoutIdx.add(grpId);
- FilePageStoreFactory pageStoreFactory = new FileVersionCheckingFactory(
- pageStoreFileIoFactory, pageStoreV1FileIoFactory, igniteCfg.getDataStorageConfiguration());
- FilePageStore idxStore =
+ FileIOFactory pageStoreFileIoFactory = this.pageStoreFileIoFactory;
+ FileIOFactory pageStoreV1FileIoFactory = this.pageStoreV1FileIoFactory;
+
+ if (encrypted) {
+ pageStoreFileIoFactory = new EncryptedFileIOFactory(
+ this.pageStoreFileIoFactory,
+ grpId,
+ pageSize(),
+ cctx.kernalContext().encryption(),
+ cctx.gridConfig().getEncryptionSpi());
+
+ pageStoreV1FileIoFactory = new EncryptedFileIOFactory(
+ this.pageStoreV1FileIoFactory,
+ grpId,
+ pageSize(),
+ cctx.kernalContext().encryption(),
+ cctx.gridConfig().getEncryptionSpi());
+ }
+
+ FileVersionCheckingFactory pageStoreFactory = new FileVersionCheckingFactory(
+ pageStoreFileIoFactory,
+ pageStoreV1FileIoFactory,
+ igniteCfg.getDataStorageConfiguration());
+
+ if (encrypted) {
+ int headerSize = pageStoreFactory.headerSize(pageStoreFactory.latestVersion());
+
+ ((EncryptedFileIOFactory)pageStoreFileIoFactory).headerSize(headerSize);
+ ((EncryptedFileIOFactory)pageStoreV1FileIoFactory).headerSize(headerSize);
+ }
+
+ PageStore idxStore =
pageStoreFactory.createPageStore(
PageMemory.FLAG_IDX,
idxFile,
allocatedTracker);
- FilePageStore[] partStores = new FilePageStore[partitions];
+ PageStore[] partStores = new PageStore[partitions];
for (int partId = 0; partId < partStores.length; partId++) {
- FilePageStore partStore =
+ PageStore partStore =
pageStoreFactory.createPageStore(
PageMemory.FLAG_DATA,
getPartitionFile(cacheWorkDir, partId),
@@ -885,7 +917,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
@Nullable IgniteCheckedException aggr) {
aggr = shutdown(holder.idxStore, cleanFile, aggr);
- for (FilePageStore store : holder.partStores) {
+ for (PageStore store : holder.partStores) {
if (store != null)
aggr = shutdown(store, cleanFile, aggr);
}
@@ -942,7 +974,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
* @param aggr Aggregating exception.
* @return Aggregating exception, if error occurred.
*/
- private IgniteCheckedException shutdown(FilePageStore store, boolean cleanFile, IgniteCheckedException aggr) {
+ private IgniteCheckedException shutdown(PageStore store, boolean cleanFile, IgniteCheckedException aggr) {
try {
if (store != null)
store.stop(cleanFile);
@@ -978,7 +1010,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
if (partId > PageIdAllocator.MAX_PARTITION_ID)
throw new IgniteCheckedException("Partition ID is reserved: " + partId);
- FilePageStore store = holder.partStores[partId];
+ PageStore store = holder.partStores[partId];
if (store == null)
throw new IgniteCheckedException("Failed to get page store for the given partition ID " +
@@ -1038,15 +1070,15 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen
*/
private static class CacheStoreHolder {
/** Index store. */
- private final FilePageStore idxStore;
+ private final PageStore idxStore;
/** Partition stores. */
- private final FilePageStore[] partStores;
+ private final PageStore[] partStores;
/**
*
*/
- CacheStoreHolder(FilePageStore idxStore, FilePageStore[] partStores) {
+ public CacheStoreHolder(PageStore idxStore, PageStore[] partStores) {
this.idxStore = idxStore;
this.partStores = partStores;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FileVersionCheckingFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FileVersionCheckingFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FileVersionCheckingFactory.java
index bc938a5..af478de 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FileVersionCheckingFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FileVersionCheckingFactory.java
@@ -62,14 +62,6 @@ public class FileVersionCheckingFactory implements FilePageStoreFactory {
this.memCfg = memCfg;
}
- /**
- * @param fileIOFactory File IO factory for V1 & V2 page store and for version checking.
- * @param memCfg Memory configuration.
- */
- public FileVersionCheckingFactory(FileIOFactory fileIOFactory, DataStorageConfiguration memCfg) {
- this(fileIOFactory, fileIOFactory, memCfg);
- }
-
/** {@inheritDoc} */
@Override public FilePageStore createPageStore(
byte type,
@@ -140,4 +132,21 @@ public class FileVersionCheckingFactory implements FilePageStoreFactory {
throw new IllegalArgumentException("Unknown version of file page store: " + ver + " for file [" + file.getAbsolutePath() + "]");
}
}
+
+ /**
+ * @param ver Version.
+ * @return Header size.
+ */
+ public int headerSize(int ver) {
+ switch (ver) {
+ case FilePageStore.VERSION:
+ return FilePageStore.HEADER_SIZE;
+
+ case FilePageStoreV2.VERSION:
+ return memCfg.getPageSize();
+
+ default:
+ throw new IllegalArgumentException("Unknown version of file page store.");
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
index 831465d..f1cc32a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/freelist/PagesList.java
@@ -276,7 +276,9 @@ public abstract class PagesList extends DataStructure {
int tailIdx = 0;
while (tailIdx < tails.length) {
- int written = curPage != 0L ? curIo.addTails(pageMem.pageSize(), curAddr, bucket, tails, tailIdx) : 0;
+ int written = curPage != 0L ?
+ curIo.addTails(pageMem.realPageSize(grpId), curAddr, bucket, tails, tailIdx) :
+ 0;
if (written == 0) {
if (nextPageId == 0L) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
index 556d997..3981d4d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java
@@ -361,6 +361,7 @@ public class MetaStorage implements DbCheckpointListener, ReadOnlyMetastorage, R
// Initialize new page.
PagePartitionMetaIO io = PagePartitionMetaIO.VERSIONS.latest();
+ //MetaStorage never encrypted so realPageSize == pageSize.
io.initNewPage(pageAddr, partMetaId, pageMem.pageSize());
treeRoot = pageMem.allocatePage(METASTORAGE_CACHE_ID, partId, PageMemory.FLAG_DATA);
@@ -537,6 +538,7 @@ public class MetaStorage implements DbCheckpointListener, ReadOnlyMetastorage, R
try {
SimpleDataPageIO io = (SimpleDataPageIO)ioVersions().forPage(pageAddr);
+ //MetaStorage never encrypted so realPageSize == pageSize.
DataPagePayload data = io.readPayload(pageAddr, itemId(nextLink), pageMem.pageSize());
nextLink = data.nextLink();
[2/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes
#4167.
Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java
new file mode 100644
index 0000000..dd3b164
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.ignite.spi.encryption;
+
+import java.nio.ByteBuffer;
+import junit.framework.TestCase;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.NotNull;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.KEYSTORE_PASSWORD;
+import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.KEYSTORE_PATH;
+
+/** */
+public class KeystoreEncryptionSpiSelfTest extends TestCase {
+ /** @throws Exception If failed. */
+ public void testCantStartWithEmptyParam() throws Exception {
+ GridTestUtils.assertThrowsWithCause(() -> {
+ EncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.spiStart("default");
+ }, IgniteException.class);
+ }
+
+ /** @throws Exception If failed. */
+ public void testCantStartWithoutPassword() throws Exception {
+ GridTestUtils.assertThrowsWithCause(() -> {
+ KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.setKeyStorePath("/ignite/is/cool/path/doesnt/exists");
+
+ encSpi.spiStart("default");
+ }, IgniteException.class);
+ }
+
+ /** @throws Exception If failed. */
+ public void testCantStartKeystoreDoesntExists() throws Exception {
+ GridTestUtils.assertThrowsWithCause(() -> {
+ KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.setKeyStorePath("/ignite/is/cool/path/doesnt/exists");
+ encSpi.setKeyStorePassword(KEYSTORE_PASSWORD.toCharArray());
+
+ encSpi.spiStart("default");
+ }, IgniteException.class);
+ }
+
+ /** @throws Exception If failed. */
+ public void testEncryptDecrypt() throws Exception {
+ EncryptionSpi encSpi = spi();
+
+ KeystoreEncryptionKey k = GridTestUtils.getFieldValue(encSpi, "masterKey");
+
+ assertNotNull(k);
+ assertNotNull(k.key());
+
+ byte[] plainText = "Just a test string to encrypt!".getBytes(UTF_8);
+ byte[] cipherText = new byte[spi().encryptedSize(plainText.length)];
+
+ encSpi.encrypt(ByteBuffer.wrap(plainText), k, ByteBuffer.wrap(cipherText));
+
+ assertNotNull(cipherText);
+ assertEquals(encSpi.encryptedSize(plainText.length), cipherText.length);
+
+ byte[] decryptedText = encSpi.decrypt(cipherText, k);
+
+ assertNotNull(decryptedText);
+ assertEquals(plainText.length, decryptedText.length);
+
+ assertEquals(new String(plainText, UTF_8), new String(decryptedText, UTF_8));
+ }
+
+ /** @throws Exception If failed. */
+ public void testKeyEncryptDecrypt() throws Exception {
+ EncryptionSpi encSpi = spi();
+
+ KeystoreEncryptionKey k = (KeystoreEncryptionKey)encSpi.create();
+
+ assertNotNull(k);
+ assertNotNull(k.key());
+
+ byte[] encGrpKey = encSpi.encryptKey(k);
+
+ assertNotNull(encGrpKey);
+ assertTrue(encGrpKey.length > 0);
+
+ KeystoreEncryptionKey k2 = (KeystoreEncryptionKey)encSpi.decryptKey(encGrpKey);
+
+ assertEquals(k.key(), k2.key());
+ }
+
+ /** */
+ @NotNull private EncryptionSpi spi() throws Exception {
+ KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+ encSpi.setKeyStorePath(KEYSTORE_PATH);
+ encSpi.setKeyStorePassword(KEYSTORE_PASSWORD.toCharArray());
+
+ GridTestUtils.invoke(encSpi, "onBeforeStart");
+
+ encSpi.spiStart("default");
+
+ return encSpi;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
index caa292b..73293ce 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
@@ -1555,51 +1555,58 @@ public final class GridTestUtils {
*/
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
@Nullable public static <T> T invoke(Object obj, String mtd, Object... params) throws Exception {
- // We cannot resolve method by parameter classes due to some of parameters can be null.
- // Search correct method among all methods collection.
- for (Method m : obj.getClass().getDeclaredMethods()) {
- // Filter methods by name.
- if (!m.getName().equals(mtd))
- continue;
-
- if (!areCompatible(params, m.getParameterTypes()))
- continue;
-
- try {
- synchronized (m) {
- // Backup accessible field state.
- boolean accessible = m.isAccessible();
+ Class<?> cls = obj.getClass();
+
+ do {
+ // We cannot resolve method by parameter classes due to some of parameters can be null.
+ // Search correct method among all methods collection.
+ for (Method m : cls.getDeclaredMethods()) {
+ // Filter methods by name.
+ if (!m.getName().equals(mtd))
+ continue;
- try {
- if (!accessible)
- m.setAccessible(true);
+ if (!areCompatible(params, m.getParameterTypes()))
+ continue;
- return (T)m.invoke(obj, params);
- }
- finally {
- // Recover accessible field state.
- if (!accessible)
- m.setAccessible(false);
+ try {
+ synchronized (m) {
+ // Backup accessible field state.
+ boolean accessible = m.isAccessible();
+
+ try {
+ if (!accessible)
+ m.setAccessible(true);
+
+ return (T)m.invoke(obj, params);
+ }
+ finally {
+ // Recover accessible field state.
+ if (!accessible)
+ m.setAccessible(false);
+ }
}
}
- }
- catch (IllegalAccessException e) {
- throw new RuntimeException("Failed to access method" +
- " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
- }
- catch (InvocationTargetException e) {
- Throwable cause = e.getCause();
+ catch (IllegalAccessException e) {
+ throw new RuntimeException("Failed to access method" +
+ " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
+ }
+ catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
- if (cause instanceof Error)
- throw (Error) cause;
+ if (cause instanceof Error)
+ throw (Error) cause;
- if (cause instanceof Exception)
- throw (Exception) cause;
+ if (cause instanceof Exception)
+ throw (Exception) cause;
- throw new RuntimeException("Failed to invoke method)" +
- " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
+ throw new RuntimeException("Failed to invoke method)" +
+ " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
+ }
}
- }
+
+ cls = cls.getSuperclass();
+ } while (cls != Object.class);
+
throw new RuntimeException("Failed to find method" +
" [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']');
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
index ee0dfa4..13387de 100755
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
@@ -839,8 +839,8 @@ public abstract class GridAbstractTest extends TestCase {
* @return Started grid.
* @throws Exception If failed.
*/
- protected Ignite startGrid(String igniteInstanceName) throws Exception {
- return startGrid(igniteInstanceName, (GridSpringResourceContext)null);
+ protected IgniteEx startGrid(String igniteInstanceName) throws Exception {
+ return (IgniteEx)startGrid(igniteInstanceName, (GridSpringResourceContext)null);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
index 7ce6209..e7876f8 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
@@ -22,6 +22,13 @@ import junit.framework.TestSuite;
import org.apache.ignite.failure.IoomFailureHandlerTest;
import org.apache.ignite.failure.SystemWorkersTerminationTest;
import org.apache.ignite.internal.ClusterBaselineNodesMetricsSelfTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheBigEntryTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheCreateTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheDestroyTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheGroupCreateTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheNodeJoinTest;
+import org.apache.ignite.internal.encryption.EncryptedCachePreconfiguredRestartTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
import org.apache.ignite.internal.GridNodeMetricsLogPdsSelfTest;
import org.apache.ignite.internal.processors.service.ServiceDeploymentOnActivationTest;
import org.apache.ignite.internal.processors.service.ServiceDeploymentOutsideBaselineTest;
@@ -62,6 +69,14 @@ public class IgniteBasicWithPersistenceTestSuite extends TestSuite {
suite.addTestSuite(GridNodeMetricsLogPdsSelfTest.class);
+ suite.addTestSuite(EncryptedCacheBigEntryTest.class);
+ suite.addTestSuite(EncryptedCacheCreateTest.class);
+ suite.addTestSuite(EncryptedCacheDestroyTest.class);
+ suite.addTestSuite(EncryptedCacheGroupCreateTest.class);
+ suite.addTestSuite(EncryptedCacheNodeJoinTest.class);
+ suite.addTestSuite(EncryptedCacheRestartTest.class);
+ suite.addTestSuite(EncryptedCachePreconfiguredRestartTest.class);
+
return suite;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
index b8ea850..ab2306e 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
@@ -53,7 +53,6 @@ import org.apache.ignite.internal.processors.port.GridPortProcessorSelfTest;
import org.apache.ignite.internal.processors.service.GridServiceClientNodeTest;
import org.apache.ignite.internal.processors.service.GridServiceContinuousQueryRedeployTest;
import org.apache.ignite.internal.processors.service.GridServiceDeploymentCompoundFutureSelfTest;
-import org.apache.ignite.internal.processors.service.GridServiceDeploymentExceptionPropagationTest;
import org.apache.ignite.internal.processors.service.GridServicePackagePrivateSelfTest;
import org.apache.ignite.internal.processors.service.GridServiceProcessorBatchDeploySelfTest;
import org.apache.ignite.internal.processors.service.GridServiceProcessorMultiNodeConfigSelfTest;
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
index 5de61ae..d5ded38 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
@@ -20,6 +20,7 @@ package org.apache.ignite.testsuites;
import junit.framework.TestSuite;
import org.apache.ignite.internal.managers.GridManagerLocalMessageListenerSelfTest;
import org.apache.ignite.internal.managers.GridNoopManagerSelfTest;
+import org.apache.ignite.spi.encryption.KeystoreEncryptionSpiSelfTest;
/**
* Grid SPI test suite.
@@ -62,6 +63,8 @@ public class IgniteSpiTestSuite extends TestSuite {
// Local Message Listener tests.
suite.addTestSuite(GridManagerLocalMessageListenerSelfTest.class);
+ suite.addTestSuite(KeystoreEncryptionSpiSelfTest.class);
+
return suite;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/resources/other_tde_keystore.jks
----------------------------------------------------------------------
diff --git a/modules/core/src/test/resources/other_tde_keystore.jks b/modules/core/src/test/resources/other_tde_keystore.jks
new file mode 100644
index 0000000..6b1f51b
Binary files /dev/null and b/modules/core/src/test/resources/other_tde_keystore.jks differ
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/core/src/test/resources/tde.jks b/modules/core/src/test/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/core/src/test/resources/tde.jks differ
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index 8688c4fbd9..5c2865a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -72,7 +72,6 @@ import org.apache.ignite.internal.sql.command.SqlIndexColumn;
import org.apache.ignite.internal.util.future.GridFinishedFuture;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.plugin.security.SecurityPermission;
import org.h2.command.Prepared;
import org.h2.command.ddl.AlterTableAlterColumn;
@@ -358,7 +357,7 @@ public class DdlStatementsProcessor {
ctx.query().dynamicTableCreate(cmd.schemaName(), e, cmd.templateName(), cmd.cacheName(),
cmd.cacheGroup(), cmd.dataRegionName(), cmd.affinityKey(), cmd.atomicityMode(),
- cmd.writeSynchronizationMode(), cmd.backups(), cmd.ifNotExists());
+ cmd.writeSynchronizationMode(), cmd.backups(), cmd.ifNotExists(), cmd.encrypted());
}
}
else if (stmt0 instanceof GridSqlDropTable) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
index de86d6a..0da77bb 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
@@ -84,6 +84,9 @@ public class GridSqlCreateTable extends GridSqlStatement {
/** Extra WITH-params. */
private List<String> params;
+ /** Encrypted flag. */
+ private boolean encrypted;
+
/**
* @return Cache name upon which new cache configuration for this table must be based.
*/
@@ -336,6 +339,20 @@ public class GridSqlCreateTable extends GridSqlStatement {
this.params = params;
}
+ /**
+ * @return Encrypted flag.
+ */
+ public boolean encrypted() {
+ return encrypted;
+ }
+
+ /**
+ * @param encrypted Encrypted flag.
+ */
+ public void encrypted(boolean encrypted) {
+ this.encrypted = encrypted;
+ }
+
/** {@inheritDoc} */
@Override public String getSQL() {
return null;
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index a653e7f..856951f 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -514,6 +514,9 @@ public class GridSqlQueryParser {
public static final String PARAM_DATA_REGION = "DATA_REGION";
/** */
+ private static final String PARAM_ENCRYPTED = "ENCRYPTED";
+
+ /** */
private final IdentityHashMap<Object, Object> h2ObjToGridObj = new IdentityHashMap<>();
/** */
@@ -1610,6 +1613,11 @@ public class GridSqlQueryParser {
break;
+ case PARAM_ENCRYPTED:
+ res.encrypted(F.isEmpty(val) || Boolean.parseBoolean(val));
+
+ break;
+
default:
throw new IgniteSQLException("Unsupported parameter: " + name, IgniteQueryErrorCode.PARSING);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java
new file mode 100644
index 0000000..4e0e3c3
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.ignite.internal.processors.cache.encryption;
+
+import java.util.List;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/** */
+public class EncryptedSqlTableTest extends EncryptedCacheRestartTest {
+ /** {@inheritDoc} */
+ @Override protected void createEncryptedCache(IgniteEx grid0, @Nullable IgniteEx grid1, String cacheName,
+ String cacheGroup, boolean putData) {
+
+ executeSql(grid0, "CREATE TABLE encrypted(ID BIGINT, NAME VARCHAR(10), PRIMARY KEY (ID)) " +
+ "WITH \"ENCRYPTED=true\"");
+ executeSql(grid0, "CREATE INDEX enc0 ON encrypted(NAME)");
+
+ if (putData) {
+ for (int i=0; i<100; i++)
+ executeSql(grid0, "INSERT INTO encrypted(ID, NAME) VALUES(?, ?)", i, "" + i);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void checkData(IgniteEx grid0) {
+ for (int i=0; i<100; i++) {
+ List<List<?>> res = executeSql(grid0, "SELECT NAME FROM encrypted WHERE ID = ?", i);
+
+ assertEquals(1, res.size());
+ assertEquals("" + i, res.get(0).get(0));
+ }
+ }
+
+ /** */
+ private List<List<?>> executeSql(IgniteEx grid, String qry, Object...args) {
+ return grid.context().query().querySqlFields(
+ new SqlFieldsQuery(qry).setSchema("PUBLIC").setArgs(args), true).getAll();
+ }
+
+ /** {@inheritDoc} */
+ @NotNull @Override protected String cacheName() {
+ return "SQL_PUBLIC_ENCRYPTED";
+ }
+
+ /** {@inheritDoc} */
+ @Override protected String keystorePath() {
+ return IgniteUtils.resolveIgnitePath("modules/indexing/src/test/resources/tde.jks").getAbsolutePath();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index 6ed914c..c97d934 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -34,7 +34,6 @@ import java.util.Random;
import java.util.UUID;
import java.util.concurrent.Callable;
import javax.cache.CacheException;
-import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;
import org.apache.ignite.binary.BinaryObject;
@@ -44,7 +43,6 @@ import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.QueryIndex;
import org.apache.ignite.cache.query.SqlFieldsQuery;
-import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
@@ -881,7 +879,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
e.setValueType("City");
queryProcessor(client()).dynamicTableCreate("PUBLIC", e, CacheMode.PARTITIONED.name(), null, null, null,
- null, CacheAtomicityMode.ATOMIC, null, 10, false);
+ null, CacheAtomicityMode.ATOMIC, null, 10, false, false);
return null;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 7c8b2f8..7633d2a 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -104,6 +104,7 @@ import org.apache.ignite.internal.processors.cache.distributed.replicated.Ignite
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQueryEvtsDisabledSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQueryP2PDisabledSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.encryption.EncryptedSqlTableTest;
import org.apache.ignite.internal.processors.cache.index.BasicIndexTest;
import org.apache.ignite.internal.processors.cache.index.DuplicateKeyValueClassesSelfTest;
import org.apache.ignite.internal.processors.cache.index.DynamicIndexClientBasicSelfTest;
@@ -472,6 +473,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
// User operation SQL
suite.addTestSuite(SqlParserUserSelfTest.class);
suite.addTestSuite(SqlUserCommandSelfTest.class);
+ suite.addTestSuite(EncryptedSqlTableTest.class);
suite.addTestSuite(ThreadLocalObjectPoolSelfTest.class);
suite.addTestSuite(H2StatementCacheSelfTest.class);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/resources/tde.jks b/modules/indexing/src/test/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/indexing/src/test/resources/tde.jks differ
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks differ
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
index 1fd8e72..71d2ba0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
@@ -64,7 +64,8 @@ namespace Apache.Ignite.Core.Tests.ApiParity
"CacheStoreSessionListenerFactories",
"PlatformConfiguration",
"ExecutorConfiguration",
- "CommunicationFailureResolver"
+ "CommunicationFailureResolver",
+ "EncryptionSpi"
};
/** Properties that are missing on .NET side. */
@@ -97,4 +98,4 @@ namespace Apache.Ignite.Core.Tests.ApiParity
KnownMappings);
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index 2861c30..354a511 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -36,6 +36,7 @@ namespace Apache.Ignite.Core.Tests
using Apache.Ignite.Core.Discovery.Tcp;
using Apache.Ignite.Core.Discovery.Tcp.Multicast;
using Apache.Ignite.Core.Discovery.Tcp.Static;
+ using Apache.Ignite.Core.Encryption.Keystore;
using Apache.Ignite.Core.Events;
using Apache.Ignite.Core.Impl.Common;
using Apache.Ignite.Core.PersistentStore;
@@ -81,6 +82,7 @@ namespace Apache.Ignite.Core.Tests
CheckDefaultValueAttributes(new IgniteConfiguration());
CheckDefaultValueAttributes(new BinaryConfiguration());
CheckDefaultValueAttributes(new TcpDiscoverySpi());
+ CheckDefaultValueAttributes(new KeystoreEncryptionSpi());
CheckDefaultValueAttributes(new CacheConfiguration());
CheckDefaultValueAttributes(new TcpDiscoveryMulticastIpFinder());
CheckDefaultValueAttributes(new TcpCommunicationSpi());
@@ -132,6 +134,14 @@ namespace Apache.Ignite.Core.Tests
Assert.AreEqual(disco.ThreadPriority, resDisco.ThreadPriority);
Assert.AreEqual(disco.TopologyHistorySize, resDisco.TopologyHistorySize);
+ var enc = (KeystoreEncryptionSpi) cfg.EncryptionSpi;
+ var resEnc = (KeystoreEncryptionSpi) resCfg.EncryptionSpi;
+
+ Assert.AreEqual(enc.MasterKeyName, resEnc.MasterKeyName);
+ Assert.AreEqual(enc.KeySize, resEnc.KeySize);
+ Assert.AreEqual(enc.KeyStorePath, resEnc.KeyStorePath);
+ Assert.AreEqual(enc.KeyStorePassword, resEnc.KeyStorePassword);
+
var ip = (TcpDiscoveryStaticIpFinder) disco.IpFinder;
var resIp = (TcpDiscoveryStaticIpFinder) resDisco.IpFinder;
@@ -684,6 +694,13 @@ namespace Apache.Ignite.Core.Tests
ThreadPriority = 6,
TopologyHistorySize = 1234567
},
+ EncryptionSpi = new KeystoreEncryptionSpi()
+ {
+ KeySize = 192,
+ KeyStorePassword = "love_sex_god",
+ KeyStorePath = "tde.jks",
+ MasterKeyName = KeystoreEncryptionSpi.DefaultMasterKeyName
+ },
IgniteInstanceName = "gridName1",
IgniteHome = IgniteHome.Resolve(null),
IncludedEventTypes = EventType.DiscoveryAll,
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 57357da..f5897c8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -161,6 +161,10 @@
<Compile Include="Discovery\Tcp\Multicast\Package-Info.cs" />
<Compile Include="Discovery\Tcp\Package-Info.cs" />
<Compile Include="Discovery\Tcp\Static\Package-Info.cs" />
+ <Compile Include="Encryption\Package-Info.cs" />
+ <Compile Include="Encryption\IEncryptionSpi.cs" />
+ <Compile Include="Encryption\Keystore\Package-Info.cs" />
+ <Compile Include="Encryption\Keystore\KeystoreEncryptionSpi.cs" />
<Compile Include="Impl\Binary\BinaryArrayEqualityComparer.cs" />
<Compile Include="Impl\Binary\BinaryProcessor.cs" />
<Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
@@ -600,4 +604,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
\ No newline at end of file
+</Project>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
index a8925ad..2e0e1a3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
@@ -161,6 +161,9 @@ namespace Apache.Ignite.Core.Cache.Configuration
/// <summary> Default value for <see cref="QueryParallelism"/>. </summary>
public const int DefaultQueryParallelism = 1;
+ /// <summary> Default value for <see cref="EncryptionEnabled"/>. </summary>
+ public const bool DefaultEncryptionEnabled = false;
+
/// <summary>
/// Gets or sets the cache name.
/// </summary>
@@ -214,6 +217,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
RebalanceBatchesPrefetchCount = DefaultRebalanceBatchesPrefetchCount;
MaxQueryIteratorsCount = DefaultMaxQueryIteratorsCount;
QueryParallelism = DefaultQueryParallelism;
+ EncryptionEnabled = DefaultEncryptionEnabled;
}
/// <summary>
@@ -329,6 +333,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
QueryDetailMetricsSize = reader.ReadInt();
QueryParallelism = reader.ReadInt();
SqlSchema = reader.ReadString();
+ EncryptionEnabled = reader.ReadBoolean();
QueryEntities = reader.ReadCollectionRaw(r => new QueryEntity(r, srvVer));
@@ -427,6 +432,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
writer.WriteInt(QueryDetailMetricsSize);
writer.WriteInt(QueryParallelism);
writer.WriteString(SqlSchema);
+ writer.WriteBoolean(EncryptionEnabled);
writer.WriteCollectionRaw(QueryEntities, srvVer);
@@ -919,5 +925,12 @@ namespace Apache.Ignite.Core.Cache.Configuration
/// </summary>
[DefaultValue(DefaultQueryParallelism)]
public int QueryParallelism { get; set; }
+
+ /// <summary>
+ /// Gets or sets encryption flag.
+ /// Default is false.
+ /// </summary>
+ [DefaultValue(DefaultEncryptionEnabled)]
+ public bool EncryptionEnabled { get; set; }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs
new file mode 100644
index 0000000..c0ea475
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Encryption
+{
+ using System.Diagnostics.CodeAnalysis;
+ using Apache.Ignite.Core.Encryption.Keystore;
+
+ /// <summary>
+ /// Encryption SPI.
+ /// <para />
+ /// Only predefined implementations are supported:
+ /// <see cref="KeystoreEncryptionSpi"/>
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")]
+ public interface IEncryptionSpi
+ {
+ // No-op.
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs
new file mode 100644
index 0000000..e1866f8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Encryption.Keystore
+{
+ using System.ComponentModel;
+ using Apache.Ignite.Core.Binary;
+
+ /// <summary>
+ /// IEncryptionSPI implementation base on JDK provided cipher algorithm implementations.
+ /// </summary>
+ public class KeystoreEncryptionSpi : IEncryptionSpi
+ {
+ /// <summary>
+ /// Default master key name.
+ /// </summary>
+ public const string DefaultMasterKeyName = "ignite.master.key";
+
+ /// <summary>
+ /// Default encryption key size.
+ /// </summary>
+ public const int DefaultKeySize = 256;
+
+ /// <summary>
+ /// Name of master key in key store.
+ /// </summary>
+ [DefaultValue(DefaultMasterKeyName)]
+ public string MasterKeyName { get; set; }
+
+ /// <summary>
+ /// Size of encryption key.
+ /// </summary>
+ [DefaultValue(DefaultKeySize)]
+ public int KeySize { get; set; }
+
+ /// <summary>
+ /// Path to key store.
+ /// </summary>
+ public string KeyStorePath { get; set; }
+
+ /// <summary>
+ /// Key store password.
+ /// </summary>
+ public string KeyStorePassword { get; set; }
+
+ /// <summary>
+ /// Empty constructor.
+ /// </summary>
+ public KeystoreEncryptionSpi()
+ {
+ MasterKeyName = DefaultMasterKeyName;
+ KeySize = DefaultKeySize;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="KeystoreEncryptionSpi"/> class.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ public KeystoreEncryptionSpi(IBinaryRawReader reader)
+ {
+ MasterKeyName = reader.ReadString();
+ KeySize = reader.ReadInt();
+ KeyStorePath = reader.ReadString();
+
+ var keyStorePassword = reader.ReadCharArray();
+
+ KeyStorePassword = keyStorePassword == null ? null : new string(keyStorePassword);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs
new file mode 100644
index 0000000..8df8b34
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs
@@ -0,0 +1,26 @@
+/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Encryption API based on standart java keystore.
+/// </summary>
+namespace Apache.Ignite.Core.Encryption.Keystore
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs
new file mode 100644
index 0000000..37cafdb
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs
@@ -0,0 +1,26 @@
+/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Encryption API.
+/// </summary>
+namespace Apache.Ignite.Core.Encryption
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index 315b27d..fc6afb6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -39,6 +39,8 @@ namespace Apache.Ignite.Core
using Apache.Ignite.Core.Deployment;
using Apache.Ignite.Core.Discovery;
using Apache.Ignite.Core.Discovery.Tcp;
+ using Apache.Ignite.Core.Encryption;
+ using Apache.Ignite.Core.Encryption.Keystore;
using Apache.Ignite.Core.Events;
using Apache.Ignite.Core.Failure;
using Apache.Ignite.Core.Impl;
@@ -373,6 +375,26 @@ namespace Apache.Ignite.Core
else
writer.WriteBoolean(false);
+ var enc = EncryptionSpi;
+
+ if (enc != null)
+ {
+ writer.WriteBoolean(true);
+
+ var keystoreEnc = enc as KeystoreEncryptionSpi;
+
+ if (keystoreEnc == null)
+ throw new InvalidOperationException("Unsupported encryption SPI: " + enc.GetType());
+
+ writer.WriteString(keystoreEnc.MasterKeyName);
+ writer.WriteInt(keystoreEnc.KeySize);
+ writer.WriteString(keystoreEnc.KeyStorePath);
+ writer.WriteCharArray(
+ keystoreEnc.KeyStorePassword == null ? null : keystoreEnc.KeyStorePassword.ToCharArray());
+ }
+ else
+ writer.WriteBoolean(false);
+
// Communication config
var comm = CommunicationSpi;
@@ -727,6 +749,9 @@ namespace Apache.Ignite.Core
// Discovery config
DiscoverySpi = r.ReadBoolean() ? new TcpDiscoverySpi(r) : null;
+ EncryptionSpi = (srvVer.CompareTo(ClientSocket.Ver120) >= 0 && r.ReadBoolean()) ?
+ new KeystoreEncryptionSpi(r) : null;
+
// Communication config
CommunicationSpi = r.ReadBoolean() ? new TcpCommunicationSpi(r) : null;
@@ -1055,6 +1080,12 @@ namespace Apache.Ignite.Core
/// Null for default communication.
/// </summary>
public ICommunicationSpi CommunicationSpi { get; set; }
+
+ /// <summary>
+ /// Gets or sets the encryption service provider.
+ /// Null for disabled encryption.
+ /// </summary>
+ public IEncryptionSpi EncryptionSpi { get; set; }
/// <summary>
/// Gets or sets a value indicating whether node should start in client mode.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index 4040610..0a55095 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -862,6 +862,11 @@
<xs:documentation>Desired query parallelism within a single node.</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="encryptionEnabled" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>Flag indicating whether cache encryption enabled.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
@@ -905,6 +910,38 @@
</xs:sequence>
</xs:complexType>
</xs:element>
+ <xs:element name="encryptionSpi" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>Encryption spi. Null for disabled encryption.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="masterKeyName" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Master key name</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="keySize" type="xs:int">
+ <xs:annotation>
+ <xs:documentation>Encryption key size.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="keyStorePath" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Key store path.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="keyStorePassword" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Key store password.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="type" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>Assembly-qualified type name.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
<xs:element name="discoverySpi" minOccurs="0">
<xs:annotation>
<xs:documentation>Discovery service provider. Null for default discovery.</xs:documentation>
@@ -999,7 +1036,7 @@
<xs:attribute name="forceServerMode" type="xs:boolean">
<xs:annotation>
<xs:documentation>
- Whether TcpDiscoverySpi is started in server mode regardless of IgniteConfiguration.ClientMode setting.
+ Whether TcpDiscoveryspi is started in server mode regardless of IgniteConfiguration.ClientMode setting.
</xs:documentation>
</xs:annotation>
</xs:attribute>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/base-enc-cfg.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/base-enc-cfg.xml b/modules/spring/src/test/config/enc/base-enc-cfg.xml
new file mode 100644
index 0000000..ad17584
--- /dev/null
+++ b/modules/spring/src/test/config/enc/base-enc-cfg.xml
@@ -0,0 +1,70 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+ <property name="peerClassLoadingEnabled" value="true"/>
+ <property name="clientMode" ref="clientMode"/>
+
+ <property name="discoverySpi">
+ <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+ <property name="ipFinder">
+ <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+ <property name="shared" value="false"/>
+ <property name="addresses">
+ <list>
+ <value>127.0.0.1:47500..47509</value>
+ </list>
+ </property>
+ </bean>
+ </property>
+ </bean>
+ </property>
+
+ <property name="dataStorageConfiguration">
+ <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
+ <property name="defaultDataRegionConfiguration">
+ <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
+ <property name="maxSize" value="#{10*1024*1024}"/>
+ <property name="persistenceEnabled" value="true"/>
+ </bean>
+ </property>
+ <property name="pageSize" value="#{4*1024}"/>
+ <property name="walMode" value="LOG_ONLY"/>
+ </bean>
+ </property>
+
+ <property name="encryptionSpi">
+ <bean class="org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi">
+ <property name="keyStorePath" value="tde.jks"/>
+ <property name="keyStorePassword" value="love_sex_god"/>
+ </bean>
+ </property>
+
+ <property name="cacheConfiguration">
+ <list>
+ <ref bean="cache.cfg" />
+ </list>
+ </property>
+ </bean>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-cache-client.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-cache-client.xml b/modules/spring/src/test/config/enc/enc-cache-client.xml
new file mode 100644
index 0000000..ba4068a
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-cache-client.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="encrypted-client"/>
+ <property name="encryptionEnabled" value="true"/>
+ </bean>
+
+ <bean id="clientMode" class="java.lang.Boolean">
+ <constructor-arg value="true"/>
+ </bean>
+
+ <import resource="base-enc-cfg.xml"/>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-cache.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-cache.xml b/modules/spring/src/test/config/enc/enc-cache.xml
new file mode 100644
index 0000000..88b3ed0
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-cache.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="encrypted"/>
+ <property name="encryptionEnabled" value="true"/>
+ </bean>
+
+ <bean id="clientMode" class="java.lang.Boolean">
+ <constructor-arg value="false"/>
+ </bean>
+
+ <import resource="base-enc-cfg.xml"/>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-group-2.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-group-2.xml b/modules/spring/src/test/config/enc/enc-group-2.xml
new file mode 100644
index 0000000..60f7031
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-group-2.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="encrypted-2"/>
+ <property name="encryptionEnabled" value="true"/>
+ <property name="groupName" value="encrypted-group"/>
+ </bean>
+
+ <bean id="clientMode" class="java.lang.Boolean">
+ <constructor-arg value="false"/>
+ </bean>
+
+ <import resource="base-enc-cfg.xml"/>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-group.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-group.xml b/modules/spring/src/test/config/enc/enc-group.xml
new file mode 100644
index 0000000..33d4659
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-group.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="encrypted"/>
+ <property name="encryptionEnabled" value="true"/>
+ <property name="groupName" value="encrypted-group"/>
+ </bean>
+
+ <bean id="clientMode" class="java.lang.Boolean">
+ <constructor-arg value="false"/>
+ </bean>
+
+ <import resource="base-enc-cfg.xml"/>
+</beans>
+
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml b/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml
new file mode 100644
index 0000000..a49ddbd
--- /dev/null
+++ b/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="encrypted-2"/>
+ <property name="encryptionEnabled" value="false"/>
+ <property name="groupName" value="encrypted-group"/>
+ </bean>
+
+ <bean id="clientMode" class="java.lang.Boolean">
+ <constructor-arg value="false"/>
+ </bean>
+
+ <import resource="base-enc-cfg.xml"/>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/not-encrypted-cache.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/not-encrypted-cache.xml b/modules/spring/src/test/config/enc/not-encrypted-cache.xml
new file mode 100644
index 0000000..a9478f6
--- /dev/null
+++ b/modules/spring/src/test/config/enc/not-encrypted-cache.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="encrypted"/>
+ <property name="encryptionEnabled" value="false"/>
+ </bean>
+
+ <bean id="clientMode" class="java.lang.Boolean">
+ <constructor-arg value="false"/>
+ </bean>
+
+ <import resource="base-enc-cfg.xml"/>
+</beans>
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java
new file mode 100644
index 0000000..fa6de21
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.ignite.encryption;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgnitionEx;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.internal.util.typedef.T2;
+
+/** */
+public class SpringEncryptedCacheRestartClientTest extends EncryptedCacheRestartTest {
+ /** {@inheritDoc} */
+ @Override protected void createEncryptedCache(IgniteEx grid0, IgniteEx grid1, String cacheName, String cacheGroup) {
+ IgniteCache<Long, String> cache = grid0.cache(cacheName());
+
+ for (long i = 0; i < 100; i++)
+ cache.put(i, "" + i);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected T2<IgniteEx, IgniteEx> startTestGrids(boolean clnPersDir) throws Exception {
+ if (clnPersDir)
+ cleanPersistenceDir();
+
+ IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-0");
+
+ IgniteEx g1 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-1");
+
+ IgniteEx client = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-cache-client.xml").getAbsolutePath(), "client");
+
+ g1.cluster().active(true);
+
+ awaitPartitionMapExchange();
+
+ return new T2<>(g1, client);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java
new file mode 100644
index 0000000..6488527
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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.ignite.encryption;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgnitionEx;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+
+import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
+
+/** */
+public class SpringEncryptedCacheRestartTest extends EncryptedCacheRestartTest {
+ /** {@inheritDoc} */
+ @Override protected void createEncryptedCache(IgniteEx grid0, IgniteEx grid1, String cacheName, String cacheGroup) {
+ IgniteCache<Long, String> cache = grid0.cache(cacheName());
+
+ for (long i = 0; i < 100; i++)
+ cache.put(i, "" + i);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected T2<IgniteEx, IgniteEx> startTestGrids(boolean clnPersDir) throws Exception {
+ if (clnPersDir)
+ cleanPersistenceDir();
+
+ IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-0");
+
+ IgniteEx g1 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-1");
+
+ g1.cluster().active(true);
+
+ awaitPartitionMapExchange();
+
+ return new T2<>(g0, g1);
+ }
+
+ /** @throws Exception If failed. */
+ public void testEncryptionKeysEqualsOnThirdNodeJoin() throws Exception {
+ T2<IgniteEx, IgniteEx> g = startTestGrids(true);
+
+ IgniteEx g2 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-group-2.xml").getAbsolutePath(), "grid-2");
+
+ Collection<String> cacheNames = Arrays.asList("encrypted", "encrypted-2");
+
+ for (String cacheName : cacheNames) {
+ IgniteInternalCache<Object, Object> enc = g.get1().cachex(cacheName);
+
+ assertNotNull(enc);
+
+ int grpId = CU.cacheGroupId(enc.name(), enc.configuration().getGroupName());
+
+ KeystoreEncryptionKey key0 = (KeystoreEncryptionKey)g.get1().context().encryption().groupKey(grpId);
+ KeystoreEncryptionKey key1 = (KeystoreEncryptionKey)g.get2().context().encryption().groupKey(grpId);
+ KeystoreEncryptionKey key2 = (KeystoreEncryptionKey)g2.context().encryption().groupKey(grpId);
+
+ assertNotNull(cacheName, key0);
+ assertNotNull(cacheName, key1);
+ assertNotNull(cacheName, key2);
+
+ assertNotNull(cacheName, key0.key());
+ assertNotNull(cacheName, key1.key());
+ assertNotNull(cacheName, key2.key());
+
+ assertEquals(cacheName, key0.key(), key1.key());
+ assertEquals(cacheName, key1.key(), key2.key());
+ }
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateEncryptedCacheGroup() throws Exception {
+ IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-group.xml").getAbsolutePath(), "grid-0");
+
+ IgniteEx g1 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-group-2.xml").getAbsolutePath(), "grid-1");
+
+ g1.cluster().active(true);
+
+ awaitPartitionMapExchange();
+
+ IgniteInternalCache<Object, Object> encrypted = g0.cachex("encrypted");
+
+ assertNotNull(encrypted);
+
+ IgniteInternalCache<Object, Object> encrypted2 = g0.cachex("encrypted-2");
+
+ assertNotNull(encrypted2);
+
+ KeystoreEncryptionKey key = (KeystoreEncryptionKey)g0.context().encryption().groupKey(
+ CU.cacheGroupId(encrypted.name(), encrypted.configuration().getGroupName()));
+
+ assertNotNull(key);
+ assertNotNull(key.key());
+
+ KeystoreEncryptionKey key2 = (KeystoreEncryptionKey)g0.context().encryption().groupKey(
+ CU.cacheGroupId(encrypted2.name(), encrypted2.configuration().getGroupName()));
+
+ assertNotNull(key2);
+ assertNotNull(key2.key());
+
+ assertEquals(key.key(), key2.key());
+ }
+
+ /** @throws Exception If failed. */
+ public void testCreateNotEncryptedCacheInEncryptedGroupFails() throws Exception {
+ IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+ IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/enc-group.xml").getAbsolutePath(), "grid-0");
+
+ assertThrowsWithCause(() -> {
+ try {
+ IgnitionEx.start(IgniteUtils.resolveIgnitePath(
+ "modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml").getAbsolutePath(), "grid-1");
+ }
+ catch (IgniteCheckedException e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+
+ /** @throws Exception If failed. */
+ public void testStartWithEncryptedOnDiskPlainInCfg() throws Exception {
+ doTestDiffCfgAndPersistentFlagVal(
+ "modules/spring/src/test/config/enc/enc-cache.xml",
+ "modules/spring/src/test/config/enc/not-encrypted-cache.xml");
+ }
+
+ /** @throws Exception If failed. */
+ public void testStartWithPlainOnDiskEncryptedInCfg() throws Exception {
+ doTestDiffCfgAndPersistentFlagVal(
+ "modules/spring/src/test/config/enc/not-encrypted-cache.xml",
+ "modules/spring/src/test/config/enc/enc-cache.xml");
+ }
+
+ /** */
+ private void doTestDiffCfgAndPersistentFlagVal(String cfg1, String cfg2) throws Exception {
+ cleanPersistenceDir();
+
+ IgniteEx g = (IgniteEx)IgnitionEx.start(IgniteUtils.resolveIgnitePath(cfg1).getAbsolutePath(), "grid-0");
+
+ g.cluster().active(true);
+
+ IgniteCache c = g.cache("encrypted");
+
+ assertNotNull(c);
+
+ stopAllGrids(false);
+
+ assertThrowsWithCause(() -> {
+ try {
+ IgnitionEx.start(IgniteUtils.resolveIgnitePath(cfg2).getAbsolutePath(), "grid-0");
+ }
+ catch (IgniteCheckedException e) {
+ throw new RuntimeException(e);
+ }
+ }, IgniteCheckedException.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
index 0e590a7..0943d51 100644
--- a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
+++ b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
@@ -23,6 +23,8 @@ import org.apache.ignite.cache.spring.GridSpringCacheManagerSelfTest;
import org.apache.ignite.cache.spring.GridSpringCacheManagerSpringBeanSelfTest;
import org.apache.ignite.cache.spring.SpringCacheManagerContextInjectionTest;
import org.apache.ignite.cache.spring.SpringCacheTest;
+import org.apache.ignite.encryption.SpringEncryptedCacheRestartClientTest;
+import org.apache.ignite.encryption.SpringEncryptedCacheRestartTest;
import org.apache.ignite.spring.injection.IgniteSpringBeanSpringResourceInjectionTest;
import org.apache.ignite.internal.IgniteSpringBeanTest;
import org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactorySelfTest;
@@ -93,6 +95,10 @@ public class IgniteSpringTestSuite extends TestSuite {
suite.addTestSuite(SpringCacheTest.class);
+ suite.addTestSuite(SpringEncryptedCacheRestartTest.class);
+ suite.addTestSuite(SpringEncryptedCacheRestartClientTest.class);
+
+ //suite.addTestSuite(GridSpringCacheManagerMultiJvmSelfTest.class);
suite.addTestSuite(GridSpringCacheManagerMultiJvmSelfTest.class);
suite.addTestSuite(GridCommandLineLoaderTest.class);
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/resources/tde.jks b/modules/spring/src/test/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/spring/src/test/resources/tde.jks differ
[4/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes
#4167.
Posted by ni...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
index e49b7e2..55c5fb5 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java
@@ -81,6 +81,7 @@ import org.apache.ignite.internal.util.OffheapReadWriteLock;
import org.apache.ignite.internal.util.future.CountDownFuture;
import org.apache.ignite.internal.util.lang.GridInClosure3X;
import org.apache.ignite.internal.util.offheap.GridOffHeapOutOfMemoryException;
+import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
import org.jetbrains.annotations.NotNull;
@@ -190,6 +191,9 @@ public class PageMemoryImpl implements PageMemoryEx {
/** Page size. */
private final int sysPageSize;
+ /** Encrypted page size. */
+ private final int encPageSize;
+
/** Shared context. */
private final GridCacheSharedContext<?, ?> ctx;
@@ -316,6 +320,8 @@ public class PageMemoryImpl implements PageMemoryEx {
sysPageSize = pageSize + PAGE_OVERHEAD;
+ encPageSize = CU.encryptedPageSize(pageSize, ctx.kernalContext().config().getEncryptionSpi());
+
rwLock = new OffheapReadWriteLock(128);
this.memMetrics = memMetrics;
@@ -484,7 +490,8 @@ public class PageMemoryImpl implements PageMemoryEx {
seg.writeLock().lock();
- boolean isTrackingPage = changeTracker != null && trackingIO.trackingPageFor(pageId, pageSize()) == pageId;
+ boolean isTrackingPage =
+ changeTracker != null && trackingIO.trackingPageFor(pageId, realPageSize(grpId)) == pageId;
try {
long relPtr = seg.loadedPages.get(
@@ -526,9 +533,9 @@ public class PageMemoryImpl implements PageMemoryEx {
// We are inside segment write lock, so no other thread can pin this tracking page yet.
// We can modify page buffer directly.
if (PageIO.getType(pageAddr) == 0) {
- trackingIO.initNewPage(pageAddr, pageId, pageSize());
+ trackingIO.initNewPage(pageAddr, pageId, realPageSize(grpId));
- if (!ctx.wal().disabled(fullId.groupId()))
+ if (!ctx.wal().disabled(fullId.groupId())) {
if (!ctx.wal().isAlwaysWriteFullPages())
ctx.wal().log(
new InitNewPageRecord(
@@ -538,8 +545,11 @@ public class PageMemoryImpl implements PageMemoryEx {
trackingIO.getVersion(), pageId
)
);
- else
- ctx.wal().log(new PageSnapshot(fullId, absPtr + PAGE_OVERHEAD, pageSize()));
+ else {
+ ctx.wal().log(new PageSnapshot(fullId, absPtr + PAGE_OVERHEAD, pageSize(),
+ realPageSize(fullId.groupId())));
+ }
+ }
}
}
@@ -947,6 +957,14 @@ public class PageMemoryImpl implements PageMemoryEx {
}
/** {@inheritDoc} */
+ @Override public int realPageSize(int grpId) {
+ if (ctx.kernalContext().encryption().groupKey(grpId) == null)
+ return pageSize();
+
+ return encPageSize;
+ }
+
+ /** {@inheritDoc} */
@Override public boolean safeToUpdate() {
if (segments != null) {
for (Segment segment : segments)
@@ -1627,7 +1645,7 @@ public class PageMemoryImpl implements PageMemoryEx {
void beforeReleaseWrite(FullPageId pageId, long ptr, boolean pageWalRec) {
if (walMgr != null && (pageWalRec || walMgr.isAlwaysWriteFullPages()) && !walMgr.disabled(pageId.groupId())) {
try {
- walMgr.log(new PageSnapshot(pageId, ptr, pageSize()));
+ walMgr.log(new PageSnapshot(pageId, ptr, pageSize(), realPageSize(pageId.groupId())));
}
catch (IgniteCheckedException e) {
// TODO ignite-db.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/BPlusIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/BPlusIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/BPlusIO.java
index 5e1cb81..349e877 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/BPlusIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/BPlusIO.java
@@ -159,7 +159,7 @@ public abstract class BPlusIO<L> extends PageIO {
/**
* @param pageAddr Page address.
- * @param pageSize Page size.
+ * @param pageSize Page size without encryption overhead.
* @return Max items count.
*/
public abstract int getMaxCount(long pageAddr, int pageSize);
@@ -331,7 +331,7 @@ public abstract class BPlusIO<L> extends PageIO {
* @param leftPageAddr Left page address.
* @param rightPageAddr Right page address.
* @param emptyBranch We are merging an empty branch.
- * @param pageSize Page size.
+ * @param pageSize Page size without encryption overhead.
* @return {@code false} If we were not able to merge.
* @throws IgniteCheckedException If failed.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
index 22d2420..ee61e25 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PageIO.java
@@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.internal.pagemem.PageIdUtils;
import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.PageUtils;
@@ -293,7 +294,7 @@ public abstract class PageIO {
}
/**
- * @param pageAddr Page addres.
+ * @param pageAddr Page address.
* @return Page type.
*/
public static int getType(long pageAddr) {
@@ -503,6 +504,8 @@ public abstract class PageIO {
* @param pageAddr Page address.
* @param pageId Page ID.
* @param pageSize Page size.
+ *
+ * @see EncryptionSpi#encryptedSize(int)
*/
public void initNewPage(long pageAddr, long pageId, int pageSize) {
setType(pageAddr, getType());
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PagePartitionCountersIO.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PagePartitionCountersIO.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PagePartitionCountersIO.java
index 68e6e2f..a3e92cf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PagePartitionCountersIO.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/io/PagePartitionCountersIO.java
@@ -107,7 +107,7 @@ public class PagePartitionCountersIO extends PageIO {
}
/**
- * @param pageSize Page size.
+ * @param pageSize Page size without encryption overhead.
* @param pageAddr Page address.
* @param cacheSizes Serialized cache size items (pairs of cache ID and its size).
* @return Number of written pairs.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandler.java
index 98c6f1f..1135868 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandler.java
@@ -23,8 +23,6 @@ import org.apache.ignite.internal.pagemem.PageMemory;
import org.apache.ignite.internal.pagemem.PageSupport;
import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager;
import org.apache.ignite.internal.pagemem.wal.record.delta.InitNewPageRecord;
-import org.apache.ignite.internal.processors.cache.GridCacheSharedManager;
-import org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
import org.apache.ignite.internal.util.GridUnsafe;
@@ -211,7 +209,7 @@ public abstract class PageHandler<X, R> {
/**
* @param pageMem Page memory.
- * @param cacheId Cache ID.
+ * @param grpId Group ID.
* @param pageId Page ID.
* @param init IO for new page initialization.
* @param wal Write ahead log.
@@ -220,20 +218,20 @@ public abstract class PageHandler<X, R> {
*/
public static void initPage(
PageMemory pageMem,
- int cacheId,
+ int grpId,
long pageId,
PageIO init,
IgniteWriteAheadLogManager wal,
PageLockListener lsnr
) throws IgniteCheckedException {
- Boolean res = writePage(pageMem, cacheId, pageId, lsnr, PageHandler.NO_OP, init, wal, null, null, 0, FALSE);
+ Boolean res = writePage(pageMem, grpId, pageId, lsnr, PageHandler.NO_OP, init, wal, null, null, 0, FALSE);
assert res != FALSE;
}
/**
* @param pageMem Page memory.
- * @param cacheId Cache ID.
+ * @param grpId Group ID.
* @param pageId Page ID.
* @param lsnr Lock listener.
* @param h Handler.
@@ -248,7 +246,7 @@ public abstract class PageHandler<X, R> {
*/
public static <X, R> R writePage(
PageMemory pageMem,
- int cacheId,
+ int grpId,
final long pageId,
PageLockListener lsnr,
PageHandler<X, R> h,
@@ -260,9 +258,9 @@ public abstract class PageHandler<X, R> {
R lockFailed
) throws IgniteCheckedException {
boolean releaseAfterWrite = true;
- long page = pageMem.acquirePage(cacheId, pageId);
+ long page = pageMem.acquirePage(grpId, pageId);
try {
- long pageAddr = writeLock(pageMem, cacheId, pageId, page, lsnr, false);
+ long pageAddr = writeLock(pageMem, grpId, pageId, page, lsnr, false);
if (pageAddr == 0L)
return lockFailed;
@@ -272,13 +270,13 @@ public abstract class PageHandler<X, R> {
try {
if (init != null) {
// It is a new page and we have to initialize it.
- doInitPage(pageMem, cacheId, pageId, page, pageAddr, init, wal);
+ doInitPage(pageMem, grpId, pageId, page, pageAddr, init, wal);
walPlc = FALSE;
}
else
init = PageIO.getPageIO(pageAddr);
- R res = h.run(cacheId, pageId, page, pageAddr, init, walPlc, arg, intArg);
+ R res = h.run(grpId, pageId, page, pageAddr, init, walPlc, arg, intArg);
ok = true;
@@ -287,19 +285,19 @@ public abstract class PageHandler<X, R> {
finally {
assert PageIO.getCrc(pageAddr) == 0; //TODO GG-11480
- if (releaseAfterWrite = h.releaseAfterWrite(cacheId, pageId, page, pageAddr, arg, intArg))
- writeUnlock(pageMem, cacheId, pageId, page, pageAddr, lsnr, walPlc, ok);
+ if (releaseAfterWrite = h.releaseAfterWrite(grpId, pageId, page, pageAddr, arg, intArg))
+ writeUnlock(pageMem, grpId, pageId, page, pageAddr, lsnr, walPlc, ok);
}
}
finally {
if (releaseAfterWrite)
- pageMem.releasePage(cacheId, pageId, page);
+ pageMem.releasePage(grpId, pageId, page);
}
}
/**
* @param pageMem Page memory.
- * @param cacheId Cache ID.
+ * @param grpId Group ID.
* @param pageId Page ID.
* @param page Page pointer.
* @param lsnr Lock listener.
@@ -315,7 +313,7 @@ public abstract class PageHandler<X, R> {
*/
public static <X, R> R writePage(
PageMemory pageMem,
- int cacheId,
+ int grpId,
long pageId,
long page,
PageLockListener lsnr,
@@ -327,7 +325,7 @@ public abstract class PageHandler<X, R> {
int intArg,
R lockFailed
) throws IgniteCheckedException {
- long pageAddr = writeLock(pageMem, cacheId, pageId, page, lsnr, false);
+ long pageAddr = writeLock(pageMem, grpId, pageId, page, lsnr, false);
if (pageAddr == 0L)
return lockFailed;
@@ -337,13 +335,13 @@ public abstract class PageHandler<X, R> {
try {
if (init != null) {
// It is a new page and we have to initialize it.
- doInitPage(pageMem, cacheId, pageId, page, pageAddr, init, wal);
+ doInitPage(pageMem, grpId, pageId, page, pageAddr, init, wal);
walPlc = FALSE;
}
else
init = PageIO.getPageIO(pageAddr);
- R res = h.run(cacheId, pageId, page, pageAddr, init, walPlc, arg, intArg);
+ R res = h.run(grpId, pageId, page, pageAddr, init, walPlc, arg, intArg);
ok = true;
@@ -352,8 +350,8 @@ public abstract class PageHandler<X, R> {
finally {
assert PageIO.getCrc(pageAddr) == 0; //TODO GG-11480
- if (h.releaseAfterWrite(cacheId, pageId, page, pageAddr, arg, intArg))
- writeUnlock(pageMem, cacheId, pageId, page, pageAddr, lsnr, walPlc, ok);
+ if (h.releaseAfterWrite(grpId, pageId, page, pageAddr, arg, intArg))
+ writeUnlock(pageMem, grpId, pageId, page, pageAddr, lsnr, walPlc, ok);
}
}
@@ -408,7 +406,7 @@ public abstract class PageHandler<X, R> {
/**
* @param pageMem Page memory.
- * @param cacheId Cache ID.
+ * @param grpId Group ID.
* @param pageId Page ID.
* @param page Page pointer.
* @param pageAddr Page address.
@@ -418,7 +416,7 @@ public abstract class PageHandler<X, R> {
*/
private static void doInitPage(
PageMemory pageMem,
- int cacheId,
+ int grpId,
long pageId,
long page,
long pageAddr,
@@ -427,11 +425,11 @@ public abstract class PageHandler<X, R> {
assert PageIO.getCrc(pageAddr) == 0; //TODO GG-11480
- init.initNewPage(pageAddr, pageId, pageMem.pageSize());
+ init.initNewPage(pageAddr, pageId, pageMem.realPageSize(grpId));
// Here we should never write full page, because it is known to be new.
- if (isWalDeltaRecordNeeded(pageMem, cacheId, pageId, page, wal, FALSE))
- wal.log(new InitNewPageRecord(cacheId, pageId,
+ if (isWalDeltaRecordNeeded(pageMem, grpId, pageId, page, wal, FALSE))
+ wal.log(new InitNewPageRecord(grpId, pageId,
init.getType(), init.getVersion(), pageId));
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
index 3f35c5f..6d379a9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
@@ -41,6 +41,7 @@ import org.apache.ignite.internal.managers.collision.GridCollisionManager;
import org.apache.ignite.internal.managers.communication.GridIoManager;
import org.apache.ignite.internal.managers.deployment.GridDeploymentManager;
import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
+import org.apache.ignite.internal.managers.encryption.GridEncryptionManager;
import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager;
import org.apache.ignite.internal.managers.failover.GridFailoverManager;
import org.apache.ignite.internal.managers.indexing.GridIndexingManager;
@@ -458,6 +459,11 @@ public class StandaloneGridKernalContext implements GridKernalContext {
}
/** {@inheritDoc} */
+ @Override public GridEncryptionManager encryption() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
@Override public WorkersRegistry workersRegistry() {
return null;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
index c33a45b..25432d3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java
@@ -42,6 +42,7 @@ import org.apache.ignite.internal.processors.cache.persistence.wal.AbstractWalRe
import org.apache.ignite.internal.processors.cache.persistence.wal.FileDescriptor;
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager.ReadFileHandle;
+import org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordDataV1Serializer.EncryptedDataEntry;
import org.apache.ignite.internal.processors.cache.persistence.wal.WalSegmentTailReachedException;
import org.apache.ignite.internal.processors.cache.persistence.wal.io.FileInput;
import org.apache.ignite.internal.processors.cache.persistence.wal.io.SegmentFileInputFactory;
@@ -375,6 +376,8 @@ class StandaloneWalRecordsIterator extends AbstractWalRecordsIterator {
final IgniteCacheObjectProcessor processor,
final CacheObjectContext fakeCacheObjCtx,
final DataEntry dataEntry) throws IgniteCheckedException {
+ if(dataEntry instanceof EncryptedDataEntry)
+ return dataEntry;
final KeyCacheObject key;
final CacheObject val;
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
index 752777a..2c8f03f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV1Serializer.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache.persistence.wal.serializer;
import java.io.DataInput;
import java.io.EOFException;
import java.io.IOException;
+import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
@@ -28,17 +29,21 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.internal.pagemem.FullPageId;
import org.apache.ignite.internal.pagemem.wal.record.CacheState;
import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord;
import org.apache.ignite.internal.pagemem.wal.record.DataEntry;
import org.apache.ignite.internal.pagemem.wal.record.DataRecord;
+import org.apache.ignite.internal.pagemem.wal.record.EncryptedRecord;
import org.apache.ignite.internal.pagemem.wal.record.LazyDataEntry;
import org.apache.ignite.internal.pagemem.wal.record.MemoryRecoveryRecord;
import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord;
import org.apache.ignite.internal.pagemem.wal.record.PageSnapshot;
import org.apache.ignite.internal.pagemem.wal.record.TxRecord;
import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType;
+import org.apache.ignite.internal.pagemem.wal.record.WalRecordCacheGroupAware;
import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertFragmentRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertRecord;
import org.apache.ignite.internal.pagemem.wal.record.delta.DataPageMvccUpdateNewTxStateHintRecord;
@@ -82,6 +87,7 @@ import org.apache.ignite.internal.pagemem.wal.record.delta.SplitForwardPageRecor
import org.apache.ignite.internal.pagemem.wal.record.delta.TrackingPageDeltaRecord;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheOperation;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
@@ -91,11 +97,23 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.BPlusInnerIO;
import org.apache.ignite.internal.processors.cache.persistence.tree.io.CacheVersionIO;
import org.apache.ignite.internal.processors.cache.persistence.wal.ByteBufferBackedDataInput;
+import org.apache.ignite.internal.processors.cache.persistence.wal.ByteBufferBackedDataInputImpl;
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
import org.apache.ignite.internal.processors.cache.persistence.wal.record.HeaderRecord;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.T3;
+import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.ENCRYPTED_DATA_RECORD;
+import static org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType.ENCRYPTED_RECORD;
+import static org.apache.ignite.internal.processors.cache.GridCacheOperation.READ;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordV1Serializer.REC_TYPE_SIZE;
+import static org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordV1Serializer.putRecordType;
/**
* Record data V1 serializer.
@@ -107,15 +125,27 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
/** Cache shared context */
private final GridCacheSharedContext cctx;
- /** Size of page used for PageMemory regions */
+ /** Size of page used for PageMemory regions. */
private final int pageSize;
+ /** Size of page without encryption overhead. */
+ private final int realPageSize;
+
/** Cache object processor to reading {@link DataEntry DataEntries} */
private final IgniteCacheObjectProcessor co;
/** Serializer of {@link TxRecord} records. */
private TxRecordSerializer txRecordSerializer;
+ /** Encryption SPI instance. */
+ private final EncryptionSpi encSpi;
+
+ /** */
+ private static final byte ENCRYPTED = 1;
+
+ /** */
+ private static final byte PLAIN = 0;
+
/**
* @param cctx Cache shared context.
*/
@@ -124,10 +154,174 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
this.txRecordSerializer = new TxRecordSerializer();
this.co = cctx.kernalContext().cacheObjects();
this.pageSize = cctx.database().pageSize();
+ this.encSpi = cctx.gridConfig().getEncryptionSpi();
+
+ //This happen on offline WAL iteration(we don't have encryption keys available).
+ if (encSpi != null)
+ this.realPageSize = CU.encryptedPageSize(pageSize, encSpi);
+ else
+ this.realPageSize = pageSize;
}
/** {@inheritDoc} */
@Override public int size(WALRecord record) throws IgniteCheckedException {
+ int clSz = plainSize(record);
+
+ if (needEncryption(record))
+ return encSpi.encryptedSize(clSz) + 4 /* groupId */ + 4 /* data size */ + REC_TYPE_SIZE;
+
+ return clSz;
+ }
+
+ /** {@inheritDoc} */
+ @Override public WALRecord readRecord(RecordType type, ByteBufferBackedDataInput in)
+ throws IOException, IgniteCheckedException {
+ if (type == ENCRYPTED_RECORD) {
+ if (encSpi == null) {
+ T2<Integer, RecordType> knownData = skipEncryptedRecord(in, true);
+
+ //This happen on offline WAL iteration(we don't have encryption keys available).
+ return new EncryptedRecord(knownData.get1(), knownData.get2());
+ }
+
+ T3<ByteBufferBackedDataInput, Integer, RecordType> clData = readEncryptedData(in, true);
+
+ //This happen during startup. On first WAL iteration we restore only metastore.
+ //So, no encryption keys available. See GridCacheDatabaseSharedManager#readMetastore
+ if (clData.get1() == null)
+ return new EncryptedRecord(clData.get2(), clData.get3());
+
+ return readPlainRecord(clData.get3(), clData.get1(), true);
+ }
+
+ return readPlainRecord(type, in, false);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeRecord(WALRecord rec, ByteBuffer buf) throws IgniteCheckedException {
+ if (needEncryption(rec)) {
+ int clSz = plainSize(rec);
+
+ ByteBuffer clData = ByteBuffer.allocate(clSz);
+
+ writePlainRecord(rec, clData);
+
+ clData.rewind();
+
+ writeEncryptedData(((WalRecordCacheGroupAware)rec).groupId(), rec.type(), clData, buf);
+
+ return;
+ }
+
+ writePlainRecord(rec, buf);
+ }
+
+ /**
+ * @param rec Record to check.
+ * @return {@code True} if this record should be encrypted.
+ */
+ private boolean needEncryption(WALRecord rec) {
+ if (!(rec instanceof WalRecordCacheGroupAware))
+ return false;
+
+ return needEncryption(((WalRecordCacheGroupAware)rec).groupId());
+ }
+
+ /**
+ * @param grpId Group id.
+ * @return {@code True} if this record should be encrypted.
+ */
+ private boolean needEncryption(int grpId) {
+ return cctx.kernalContext().encryption().groupKey(grpId) != null;
+ }
+
+ /**
+ * Reads and decrypt data from {@code in} stream.
+ *
+ * @param in Input stream.
+ * @param readType If {@code true} plain record type will be read from {@code in}.
+ * @return Plain data stream, group id, plain record type,
+ * @throws IOException If failed.
+ * @throws IgniteCheckedException If failed.
+ */
+ private T3<ByteBufferBackedDataInput, Integer, RecordType> readEncryptedData(ByteBufferBackedDataInput in,
+ boolean readType)
+ throws IOException, IgniteCheckedException {
+ int grpId = in.readInt();
+ int encRecSz = in.readInt();
+ RecordType plainRecType = null;
+
+ if (readType)
+ plainRecType = RecordV1Serializer.readRecordType(in);
+
+ byte[] encData = new byte[encRecSz];
+
+ in.readFully(encData);
+
+ Serializable key = cctx.kernalContext().encryption().groupKey(grpId);
+
+ if (key == null)
+ return new T3<>(null, grpId, plainRecType);
+
+ byte[] clData = encSpi.decrypt(encData, key);
+
+ return new T3<>(new ByteBufferBackedDataInputImpl().buffer(ByteBuffer.wrap(clData)), grpId, plainRecType);
+ }
+
+ /**
+ * Reads encrypted record without decryption.
+ * Should be used only for a offline WAL iteration.
+ *
+ * @param in Data stream.
+ * @param readType If {@code true} plain record type will be read from {@code in}.
+ * @return Group id and type of skipped record.
+ */
+ private T2<Integer, RecordType> skipEncryptedRecord(ByteBufferBackedDataInput in, boolean readType)
+ throws IOException, IgniteCheckedException {
+ int grpId = in.readInt();
+ int encRecSz = in.readInt();
+ RecordType plainRecType = null;
+
+ if (readType)
+ plainRecType = RecordV1Serializer.readRecordType(in);
+
+ int skipped = in.skipBytes(encRecSz);
+
+ assert skipped == encRecSz;
+
+ return new T2<>(grpId, plainRecType);
+ }
+
+ /**
+ * Writes encrypted {@code clData} to {@code dst} stream.
+ *
+ * @param grpId Group id;
+ * @param plainRecType Plain record type
+ * @param clData Plain data.
+ * @param dst Destination buffer.
+ */
+ private void writeEncryptedData(int grpId, @Nullable RecordType plainRecType, ByteBuffer clData, ByteBuffer dst) {
+ int dtSz = encSpi.encryptedSize(clData.capacity());
+
+ dst.putInt(grpId);
+ dst.putInt(dtSz);
+
+ if (plainRecType != null)
+ putRecordType(dst, plainRecType);
+
+ Serializable key = cctx.kernalContext().encryption().groupKey(grpId);
+
+ assert key != null;
+
+ encSpi.encrypt(clData, key, dst);
+ }
+
+ /**
+ * @param record Record to measure.
+ * @return Plain(without encryption) size of serialized rec in bytes.
+ * @throws IgniteCheckedException If failed.
+ */
+ int plainSize(WALRecord record) throws IgniteCheckedException {
switch (record.type()) {
case PAGE_RECORD:
assert record instanceof PageSnapshot;
@@ -313,8 +507,19 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
}
}
- /** {@inheritDoc} */
- @Override public WALRecord readRecord(WALRecord.RecordType type, ByteBufferBackedDataInput in) throws IOException, IgniteCheckedException {
+ /**
+ * Reads {@code WalRecord} of {@code type} from input.
+ * Input should be plain(not encrypted).
+ *
+ * @param type Record type.
+ * @param in Input
+ * @param encrypted Record was encrypted.
+ * @return Deserialized record.
+ * @throws IOException If failed.
+ * @throws IgniteCheckedException If failed.
+ */
+ WALRecord readPlainRecord(RecordType type, ByteBufferBackedDataInput in,
+ boolean encrypted) throws IOException, IgniteCheckedException {
WALRecord res;
switch (type) {
@@ -326,7 +531,7 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
in.readFully(arr);
- res = new PageSnapshot(new FullPageId(pageId, cacheId), arr);
+ res = new PageSnapshot(new FullPageId(pageId, cacheId), arr, encrypted ? realPageSize : pageSize);
break;
@@ -401,7 +606,19 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
List<DataEntry> entries = new ArrayList<>(entryCnt);
for (int i = 0; i < entryCnt; i++)
- entries.add(readDataEntry(in));
+ entries.add(readPlainDataEntry(in));
+
+ res = new DataRecord(entries, 0L);
+
+ break;
+
+ case ENCRYPTED_DATA_RECORD:
+ entryCnt = in.readInt();
+
+ entries = new ArrayList<>(entryCnt);
+
+ for (int i = 0; i < entryCnt; i++)
+ entries.add(readEncryptedDataEntry(in));
res = new DataRecord(entries, 0L);
@@ -911,8 +1128,14 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
return res;
}
- /** {@inheritDoc} */
- @Override public void writeRecord(WALRecord rec, ByteBuffer buf) throws IgniteCheckedException {
+ /**
+ * Write {@code rec} to {@code buf} without encryption.
+ *
+ * @param rec Record to serialize.
+ * @param buf Output buffer.
+ * @throws IgniteCheckedException If failed.
+ */
+ void writePlainRecord(WALRecord rec, ByteBuffer buf) throws IgniteCheckedException {
switch (rec.type()) {
case PAGE_RECORD:
PageSnapshot snap = (PageSnapshot)rec;
@@ -997,8 +1220,14 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
buf.putInt(dataRec.writeEntries().size());
- for (DataEntry dataEntry : dataRec.writeEntries())
- putDataEntry(buf, dataEntry);
+ boolean encrypted = isDataRecordEncrypted(dataRec);
+
+ for (DataEntry dataEntry : dataRec.writeEntries()) {
+ if (encrypted)
+ putEncryptedDataEntry(buf, dataEntry);
+ else
+ putPlainDataEntry(buf, dataEntry);
+ }
break;
@@ -1482,8 +1711,36 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
/**
* @param buf Buffer to write to.
* @param entry Data entry.
+ * @throws IgniteCheckedException If failed.
+ */
+ void putEncryptedDataEntry(ByteBuffer buf, DataEntry entry) throws IgniteCheckedException {
+ DynamicCacheDescriptor desc = cctx.cache().cacheDescriptor(entry.cacheId());
+
+ if (desc != null && needEncryption(desc.groupId())) {
+ int clSz = entrySize(entry);
+
+ ByteBuffer clData = ByteBuffer.allocate(clSz);
+
+ putPlainDataEntry(clData, entry);
+
+ clData.rewind();
+
+ buf.put(ENCRYPTED);
+
+ writeEncryptedData(desc.groupId(), null, clData, buf);
+ }
+ else {
+ buf.put(PLAIN);
+
+ putPlainDataEntry(buf, entry);
+ }
+ }
+
+ /**
+ * @param buf Buffer to write to.
+ * @param entry Data entry.
*/
- static void putDataEntry(ByteBuffer buf, DataEntry entry) throws IgniteCheckedException {
+ void putPlainDataEntry(ByteBuffer buf, DataEntry entry) throws IgniteCheckedException {
buf.putInt(entry.cacheId());
if (!entry.key().putValue(buf))
@@ -1550,8 +1807,35 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
/**
* @param in Input to read from.
* @return Read entry.
+ * @throws IOException If failed.
+ * @throws IgniteCheckedException If failed.
+ */
+ DataEntry readEncryptedDataEntry(ByteBufferBackedDataInput in) throws IOException, IgniteCheckedException {
+ boolean needDecryption = in.readByte() == ENCRYPTED;
+
+ if (needDecryption) {
+ if (encSpi == null) {
+ skipEncryptedRecord(in, false);
+
+ return new EncryptedDataEntry();
+ }
+
+ T3<ByteBufferBackedDataInput, Integer, RecordType> clData = readEncryptedData(in, false);
+
+ if (clData.get1() == null)
+ return null;
+
+ return readPlainDataEntry(clData.get1());
+ }
+
+ return readPlainDataEntry(in);
+ }
+
+ /**
+ * @param in Input to read from.
+ * @return Read entry.
*/
- DataEntry readDataEntry(ByteBufferBackedDataInput in) throws IOException, IgniteCheckedException {
+ DataEntry readPlainDataEntry(ByteBufferBackedDataInput in) throws IOException, IgniteCheckedException {
int cacheId = in.readInt();
int keySize = in.readInt();
@@ -1622,6 +1906,33 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
}
/**
+ * @param rec Record.
+ * @return Real record type.
+ */
+ RecordType recordType(WALRecord rec) {
+ if (needEncryption(rec))
+ return ENCRYPTED_RECORD;
+
+ if (rec.type() != DATA_RECORD)
+ return rec.type();
+
+ return isDataRecordEncrypted((DataRecord)rec) ? ENCRYPTED_DATA_RECORD : DATA_RECORD;
+ }
+
+ /**
+ * @param rec Data record.
+ * @return {@code True} if this data record should be encrypted.
+ */
+ boolean isDataRecordEncrypted(DataRecord rec) {
+ for (DataEntry e : rec.writeEntries()) {
+ if(needEncryption(cctx.cacheContext(e.cacheId()).groupId()))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
* @param buf Buffer to read from.
* @return Read map.
*/
@@ -1683,10 +1994,22 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
* @throws IgniteCheckedException If failed to obtain the length of one of the entries.
*/
private int dataSize(DataRecord dataRec) throws IgniteCheckedException {
+ boolean encrypted = isDataRecordEncrypted(dataRec);
+
int sz = 0;
- for (DataEntry entry : dataRec.writeEntries())
- sz += entrySize(entry);
+ for (DataEntry entry : dataRec.writeEntries()) {
+ int clSz = entrySize(entry);
+
+ if (needEncryption(cctx.cacheContext(entry.cacheId()).groupId()))
+ sz += encSpi.encryptedSize(clSz) + 1 /* encrypted flag */ + 4 /* groupId */ + 4 /* data size */;
+ else {
+ sz += clSz;
+
+ if (encrypted)
+ sz += 1 /* encrypted flag */;
+ }
+ }
return sz;
}
@@ -1735,4 +2058,10 @@ public class RecordDataV1Serializer implements RecordDataSerializer {
return size;
}
+
+ public static class EncryptedDataEntry extends DataEntry {
+ EncryptedDataEntry() {
+ super(0, null, null, READ, null, null, 0, 0, 0);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV2Serializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV2Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV2Serializer.java
index b760547..5f29dd5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV2Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordDataV2Serializer.java
@@ -35,6 +35,8 @@ import org.apache.ignite.internal.pagemem.wal.record.ExchangeRecord;
import org.apache.ignite.internal.pagemem.wal.record.SnapshotRecord;
import org.apache.ignite.internal.pagemem.wal.record.TxRecord;
import org.apache.ignite.internal.pagemem.wal.record.WALRecord;
+import org.apache.ignite.internal.pagemem.wal.record.WALRecord.RecordType;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.persistence.wal.ByteBufferBackedDataInput;
import org.apache.ignite.internal.processors.cache.persistence.wal.FileWALPointer;
import org.apache.ignite.internal.processors.cache.persistence.wal.record.HeaderRecord;
@@ -42,12 +44,9 @@ import org.apache.ignite.internal.processors.cache.persistence.wal.record.Header
/**
* Record data V2 serializer.
*/
-public class RecordDataV2Serializer implements RecordDataSerializer {
+public class RecordDataV2Serializer extends RecordDataV1Serializer implements RecordDataSerializer {
/** Length of HEADER record data. */
- static final int HEADER_RECORD_DATA_SIZE = /*Magic*/8 + /*Version*/4;
-
- /** V1 data serializer delegate. */
- private final RecordDataV1Serializer delegateSerializer;
+ private static final int HEADER_RECORD_DATA_SIZE = /*Magic*/8 + /*Version*/4;
/** Serializer of {@link TxRecord} records. */
private final TxRecordSerializer txRecordSerializer;
@@ -55,15 +54,16 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
/**
* Create an instance of V2 data serializer.
*
- * @param delegateSerializer V1 data serializer.
+ * @param cctx Cache shared context.
*/
- public RecordDataV2Serializer(RecordDataV1Serializer delegateSerializer) {
- this.delegateSerializer = delegateSerializer;
+ public RecordDataV2Serializer(GridCacheSharedContext cctx) {
+ super(cctx);
+
this.txRecordSerializer = new TxRecordSerializer();
}
/** {@inheritDoc} */
- @Override public int size(WALRecord rec) throws IgniteCheckedException {
+ @Override protected int plainSize(WALRecord rec) throws IgniteCheckedException {
switch (rec.type()) {
case HEADER_RECORD:
return HEADER_RECORD_DATA_SIZE;
@@ -81,7 +81,7 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
return 18 + cacheStatesSize + (walPtr == null ? 0 : 16);
case DATA_RECORD:
- return delegateSerializer.size(rec) + 8/*timestamp*/;
+ return super.plainSize(rec) + 8/*timestamp*/;
case SNAPSHOT:
return 8 + 1;
@@ -93,14 +93,15 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
return txRecordSerializer.size((TxRecord)rec);
default:
- return delegateSerializer.size(rec);
+ return super.plainSize(rec);
}
}
/** {@inheritDoc} */
- @Override public WALRecord readRecord(
- WALRecord.RecordType type,
- ByteBufferBackedDataInput in
+ @Override WALRecord readPlainRecord(
+ RecordType type,
+ ByteBufferBackedDataInput in,
+ boolean encrypted
) throws IOException, IgniteCheckedException {
switch (type) {
case CHECKPOINT_RECORD:
@@ -130,9 +131,21 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
List<DataEntry> entries = new ArrayList<>(entryCnt);
for (int i = 0; i < entryCnt; i++)
- entries.add(delegateSerializer.readDataEntry(in));
+ entries.add(readPlainDataEntry(in));
+
+ return new DataRecord(entries, timeStamp);
+
+ case ENCRYPTED_DATA_RECORD:
+ entryCnt = in.readInt();
+ timeStamp = in.readLong();
+
+ entries = new ArrayList<>(entryCnt);
+
+ for (int i = 0; i < entryCnt; i++)
+ entries.add(readEncryptedDataEntry(in));
return new DataRecord(entries, timeStamp);
+
case SNAPSHOT:
long snpId = in.readLong();
byte full = in.readByte();
@@ -150,13 +163,12 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
return txRecordSerializer.read(in);
default:
- return delegateSerializer.readRecord(type, in);
+ return super.readPlainRecord(type, in, encrypted);
}
-
}
/** {@inheritDoc} */
- @Override public void writeRecord(WALRecord rec, ByteBuffer buf) throws IgniteCheckedException {
+ @Override protected void writePlainRecord(WALRecord rec, ByteBuffer buf) throws IgniteCheckedException {
if (rec instanceof HeaderRecord)
throw new UnsupportedOperationException("Writing header records is forbidden since version 2 of serializer");
@@ -193,8 +205,14 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
buf.putInt(dataRec.writeEntries().size());
buf.putLong(dataRec.timestamp());
- for (DataEntry dataEntry : dataRec.writeEntries())
- RecordDataV1Serializer.putDataEntry(buf, dataEntry);
+ boolean encrypted = isDataRecordEncrypted(dataRec);
+
+ for (DataEntry dataEntry : dataRec.writeEntries()) {
+ if (encrypted)
+ putEncryptedDataEntry(buf, dataEntry);
+ else
+ putPlainDataEntry(buf, dataEntry);
+ }
break;
@@ -221,7 +239,7 @@ public class RecordDataV2Serializer implements RecordDataSerializer {
break;
default:
- delegateSerializer.writeRecord(rec, buf);
+ super.writePlainRecord(rec, buf);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordSerializerFactoryImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordSerializerFactoryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordSerializerFactoryImpl.java
index 2e2e2f8..c149817 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordSerializerFactoryImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordSerializerFactoryImpl.java
@@ -77,11 +77,8 @@ public class RecordSerializerFactoryImpl implements RecordSerializerFactory {
recordDeserializeFilter);
case 2:
- RecordDataV2Serializer dataV2Serializer = new RecordDataV2Serializer(
- new RecordDataV1Serializer(cctx));
-
return new RecordV2Serializer(
- dataV2Serializer,
+ new RecordDataV2Serializer(cctx),
needWritePointer,
marshalledMode,
skipPositionCheck,
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
index afd770d..c65f37c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV1Serializer.java
@@ -170,7 +170,7 @@ public class RecordV1Serializer implements RecordSerializer {
/** {@inheritDoc} */
@Override public void writeWithHeaders(WALRecord rec, ByteBuffer buf) throws IgniteCheckedException {
// Write record type.
- putRecordType(buf, rec);
+ putRecordType(buf, dataSerializer.recordType(rec));
// SWITCH_SEGMENT_RECORD should have only type, no need to write pointer.
if (rec.type() == SWITCH_SEGMENT_RECORD)
@@ -326,10 +326,10 @@ public class RecordV1Serializer implements RecordSerializer {
* Writes record type to given {@code buf}.
*
* @param buf Buffer to write record type.
- * @param rec WAL record.
+ * @param type WAL record type.
*/
- static void putRecordType(ByteBuffer buf, WALRecord rec) {
- buf.put((byte)(rec.type().ordinal() + 1));
+ static void putRecordType(ByteBuffer buf, RecordType type) {
+ buf.put((byte)(type.ordinal() + 1));
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
index e112522..d27a331 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/serializer/RecordV2Serializer.java
@@ -174,7 +174,7 @@ public class RecordV2Serializer implements RecordSerializer {
ByteBuffer buf
) throws IgniteCheckedException {
// Write record type.
- RecordV1Serializer.putRecordType(buf, record);
+ RecordV1Serializer.putRecordType(buf, dataSerializer.recordType(record));
// SWITCH_SEGMENT_RECORD should have only type, no need to write pointer.
if (record.type() == SWITCH_SEGMENT_RECORD)
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ChangeGlobalStateMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ChangeGlobalStateMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ChangeGlobalStateMessage.java
index 81855fc..51a65bb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ChangeGlobalStateMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/ChangeGlobalStateMessage.java
@@ -70,6 +70,9 @@ public class ChangeGlobalStateMessage implements DiscoveryCustomMessage {
* @param initiatingNodeId Node initiated state change.
* @param storedCfgs Configurations read from persistent store.
* @param activate New cluster state.
+ * @param baselineTopology Baseline topology.
+ * @param forceChangeBaselineTopology Force change baseline topology flag.
+ * @param timestamp Timestamp.
*/
public ChangeGlobalStateMessage(
UUID reqId,
@@ -78,8 +81,7 @@ public class ChangeGlobalStateMessage implements DiscoveryCustomMessage {
boolean activate,
BaselineTopology baselineTopology,
boolean forceChangeBaselineTopology,
- long timestamp
- ) {
+ long timestamp) {
assert reqId != null;
assert initiatingNodeId != null;
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridClusterStateProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridClusterStateProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridClusterStateProcessor.java
index 2b70998..d52d388 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridClusterStateProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cluster/GridClusterStateProcessor.java
@@ -1170,6 +1170,8 @@ public class GridClusterStateProcessor extends GridProcessorAdapter implements I
ctx.task().onActivate(ctx);
+ ctx.encryption().onActivate(ctx);
+
if (log.isInfoEnabled())
log.info("Successfully performed final activation steps [nodeId="
+ ctx.localNodeId() + ", client=" + client + ", topVer=" + req.topologyVersion() + "]");
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index 8e66102..25b9cb8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -69,6 +69,7 @@ import org.apache.ignite.configuration.PersistentStoreConfiguration;
import org.apache.ignite.configuration.SqlConnectorConfiguration;
import org.apache.ignite.configuration.TransactionConfiguration;
import org.apache.ignite.configuration.WALMode;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
import org.apache.ignite.events.Event;
import org.apache.ignite.failure.FailureHandler;
import org.apache.ignite.failure.NoOpFailureHandler;
@@ -99,6 +100,8 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.spi.encryption.noop.NoopEncryptionSpi;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
import org.apache.ignite.spi.eventstorage.EventStorageSpi;
import org.apache.ignite.spi.eventstorage.NoopEventStorageSpi;
import org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi;
@@ -220,6 +223,7 @@ public class PlatformConfigurationUtils {
ccfg.setQueryDetailMetricsSize(in.readInt());
ccfg.setQueryParallelism(in.readInt());
ccfg.setSqlSchema(in.readString());
+ ccfg.setEncryptionEnabled(in.readBoolean());
int qryEntCnt = in.readInt();
@@ -702,6 +706,7 @@ public class PlatformConfigurationUtils {
readCacheConfigurations(in, cfg, ver);
readDiscoveryConfiguration(in, cfg);
+ readEncryptionConfiguration(in, cfg, ver);
if (in.readBoolean()) {
TcpCommunicationSpi comm = new TcpCommunicationSpi();
@@ -943,6 +948,30 @@ public class PlatformConfigurationUtils {
}
/**
+ * Reads encryption configuration
+ * @param in Reader.
+ * @param cfg Configuration.
+ * @param ver Client version.
+ */
+ private static void readEncryptionConfiguration(BinaryRawReaderEx in, IgniteConfiguration cfg,
+ ClientListenerProtocolVersion ver) {
+ if (ver.compareTo(VER_1_2_0) < 0 || !in.readBoolean()) {
+ cfg.setEncryptionSpi(new NoopEncryptionSpi());
+
+ return;
+ }
+
+ KeystoreEncryptionSpi enc = new KeystoreEncryptionSpi();
+
+ enc.setMasterKeyName(in.readString());
+ enc.setKeySize(in.readInt());
+ enc.setKeyStorePath(in.readString());
+ enc.setKeyStorePassword(in.readCharArray());
+
+ cfg.setEncryptionSpi(enc);
+ }
+
+ /**
* Writes cache configuration.
*
* @param writer Writer.
@@ -1003,6 +1032,7 @@ public class PlatformConfigurationUtils {
writer.writeInt(ccfg.getQueryDetailMetricsSize());
writer.writeInt(ccfg.getQueryParallelism());
writer.writeString(ccfg.getSqlSchema());
+ writer.writeBoolean(ccfg.isEncryptionEnabled());
Collection<QueryEntity> qryEntities = ccfg.getQueryEntities();
@@ -1253,6 +1283,7 @@ public class PlatformConfigurationUtils {
w.writeInt(0);
writeDiscoveryConfiguration(w, cfg.getDiscoverySpi());
+ writeEncryptionConfiguration(w, cfg.getEncryptionSpi(), ver);
CommunicationSpi comm = cfg.getCommunicationSpi();
@@ -1462,6 +1493,34 @@ public class PlatformConfigurationUtils {
}
/**
+ * Writes encryption configuration.
+ *
+ * @param w Writer.
+ * @param enc Encryption Spi.
+ * @param ver Client version.
+ */
+ private static void writeEncryptionConfiguration(BinaryRawWriter w, EncryptionSpi enc,
+ ClientListenerProtocolVersion ver) {
+ if (ver.compareTo(VER_1_2_0) < 0)
+ return;
+
+ if (enc instanceof NoopEncryptionSpi) {
+ w.writeBoolean(false);
+
+ return;
+ }
+
+ KeystoreEncryptionSpi keystoreEnc = (KeystoreEncryptionSpi)enc;
+
+ w.writeBoolean(true);
+
+ w.writeString(keystoreEnc.getMasterKeyName());
+ w.writeInt(keystoreEnc.getKeySize());
+ w.writeString(keystoreEnc.getKeyStorePath());
+ w.writeCharArray(keystoreEnc.getKeyStorePwd());
+ }
+
+ /**
* Writes enum as byte.
*
* @param w Writer.
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index eb3f2a7..b5b104d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1484,13 +1484,14 @@ public class GridQueryProcessor extends GridProcessorAdapter {
* @param writeSyncMode Write synchronization mode.
* @param backups Backups.
* @param ifNotExists Quietly ignore this command if table already exists.
+ * @param encrypted Encrypted flag.
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
public void dynamicTableCreate(String schemaName, QueryEntity entity, String templateName, String cacheName,
String cacheGroup, @Nullable String dataRegion, String affinityKey, @Nullable CacheAtomicityMode atomicityMode,
- @Nullable CacheWriteSynchronizationMode writeSyncMode, @Nullable Integer backups, boolean ifNotExists)
- throws IgniteCheckedException {
+ @Nullable CacheWriteSynchronizationMode writeSyncMode, @Nullable Integer backups, boolean ifNotExists,
+ boolean encrypted) throws IgniteCheckedException {
assert !F.isEmpty(templateName);
assert backups == null || backups >= 0;
@@ -1534,6 +1535,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
if (backups != null)
ccfg.setBackups(backups);
+ ccfg.setEncryptionEnabled(encrypted);
ccfg.setSqlSchema(schemaName);
ccfg.setSqlEscapeAll(true);
ccfg.setQueryEntities(Collections.singleton(entity));
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index b8ba742..3ffbb00 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -32,10 +32,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInput;
+import java.io.ObjectInputStream;
import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
+import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
@@ -107,6 +110,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Random;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.StringTokenizer;
@@ -477,6 +481,9 @@ public abstract class IgniteUtils {
/** Ignite Work Directory. */
public static final String IGNITE_WORK_DIR = System.getenv(IgniteSystemProperties.IGNITE_WORK_DIR);
+ /** Random is used to get random server node to authentication from client node. */
+ private static final Random RND = new Random(System.currentTimeMillis());
+
/** Clock timer. */
private static Thread timer;
@@ -10339,6 +10346,43 @@ public abstract class IgniteUtils {
}
/**
+ * Serialize object to byte array.
+ *
+ * @param obj Object.
+ * @return Serialized object.
+ */
+ public static byte[] toBytes(Serializable obj) {
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+
+ oos.writeObject(obj);
+ oos.flush();
+
+ return bos.toByteArray();
+ }
+ catch (IOException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /**
+ * Deserialize object from byte array.
+ *
+ * @param data Serialized object.
+ * @return Object.
+ */
+ public static <T> T fromBytes(byte[] data) {
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new ObjectInputStream(bis)) {
+
+ return (T)ois.readObject();
+ }
+ catch (IOException | ClassNotFoundException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /**
* Return count of regular file in the directory (including in sub-directories)
*
* @param dir path to directory
@@ -10580,6 +10624,27 @@ public abstract class IgniteUtils {
}
/**
+ * @param ctx Kernel context.
+ * @return Random alive server node.
+ */
+ public static ClusterNode randomServerNode(GridKernalContext ctx) {
+ Collection<ClusterNode> aliveNodes = ctx.discovery().aliveServerNodes();
+
+ int rndIdx = RND.nextInt(aliveNodes.size()) + 1;
+
+ int i = 0;
+ ClusterNode rndNode = null;
+
+ for (Iterator<ClusterNode> it = aliveNodes.iterator(); i < rndIdx && it.hasNext(); i++)
+ rndNode = it.next();
+
+ if (rndNode == null)
+ assert rndNode != null;
+
+ return rndNode;
+ }
+
+ /**
*
*/
public static class ReentrantReadWriteLockTracer implements ReadWriteLock {
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
index f9c4d9d..ce5076b 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
@@ -298,13 +298,13 @@ public class GridFunc {
* @param delim Delimiter (optional).
* @return Concatenated string.
*/
- public static String concat(Iterable<String> c, @Nullable String delim) {
+ public static String concat(Iterable<?> c, @Nullable String delim) {
A.notNull(c, "c");
IgniteReducer<? super String, String> f = new StringConcatReducer(delim);
- for (String x : c)
- if (!f.collect(x))
+ for (Object x : c)
+ if (!f.collect(x == null ? null : x.toString()))
break;
return f.reduce();
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/spi/encryption/EncryptionSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/EncryptionSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/EncryptionSpi.java
new file mode 100644
index 0000000..693cefd
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/EncryptionSpi.java
@@ -0,0 +1,113 @@
+/*
+ * 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.ignite.spi.encryption;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.spi.IgniteSpi;
+
+/**
+ * SPI provides encryption features for an Ignite.
+ */
+public interface EncryptionSpi extends IgniteSpi {
+ /**
+ * Returns master key digest.
+ * Should always return same digest for a same key.
+ * Digest used for a configuration consistency check.
+ *
+ * @return Master key digest.
+ */
+ byte[] masterKeyDigest();
+
+ /**
+ * Creates new key for an encryption/decryption of cache persistent data: pages, WAL records.
+ *
+ * @return Newly created encryption key.
+ * @throws IgniteException If key creation failed.
+ */
+ Serializable create() throws IgniteException;
+
+ /**
+ * Encrypts data.
+ *
+ * @param data Data to encrypt.
+ * @param key Encryption key.
+ * @param res Destination buffer.
+ */
+ void encrypt(ByteBuffer data, Serializable key, ByteBuffer res);
+
+ /**
+ * Encrypts data without padding info.
+ *
+ * @param data Data to encrypt.
+ * @param key Encryption key.
+ * @param res Destination buffer.
+ */
+ void encryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res);
+
+ /**
+ * Decrypts data encrypted with {@link #encrypt(ByteBuffer, Serializable, ByteBuffer)}
+ *
+ * @param data Data to decrypt.
+ * @param key Encryption key.
+ */
+ byte[] decrypt(byte[] data, Serializable key);
+
+ /**
+ * Decrypts data encrypted with {@link #encryptNoPadding(ByteBuffer, Serializable, ByteBuffer)}
+ *
+ * @param data Data to decrypt.
+ * @param key Encryption key.
+ */
+ void decryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res);
+
+ /**
+ * Encrypts key.
+ * Adds some info to check key integrity on decryption.
+ *
+ * @param key Key to encrypt.
+ * @return Encrypted key.
+ */
+ byte[] encryptKey(Serializable key);
+
+ /**
+ * Decrypts key and checks it integrity.
+ *
+ * @param key Key to decrypt.
+ * @return Encrypted key.
+ */
+ Serializable decryptKey(byte[] key);
+
+ /**
+ * @param dataSize Size of plain data in bytes.
+ * @return Size of encrypted data in bytes for padding encryption mode.
+ */
+ int encryptedSize(int dataSize);
+
+ /**
+ * @param dataSize Size of plain data in bytes.
+ * @return Size of encrypted data in bytes for nopadding encryption mode.
+ */
+ int encryptedSizeNoPadding(int dataSize);
+
+ /**
+ * @return Encrypted data block size.
+ */
+ int blockSize();
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionKey.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionKey.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionKey.java
new file mode 100644
index 0000000..c2577c7
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionKey.java
@@ -0,0 +1,84 @@
+/*
+ * 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.ignite.spi.encryption.keystore;
+
+import java.io.Serializable;
+import java.security.Key;
+import java.util.Arrays;
+import java.util.Objects;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * {@code EncryptionKey} implementation based on java security.
+ *
+ * @see Key
+ * @see KeystoreEncryptionSpi
+ */
+public final class KeystoreEncryptionKey implements Serializable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * Encryption key.
+ */
+ private final Key k;
+
+ /**
+ * Key digest.
+ */
+ @Nullable final byte[] digest;
+
+ /**
+ * @param k Encryption key.
+ * @param digest Message digest.
+ */
+ KeystoreEncryptionKey(Key k, @Nullable byte[] digest) {
+ this.k = k;
+ this.digest = digest;
+ }
+
+ /**
+ * Encryption key.
+ */
+ public Key key() {
+ return k;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ KeystoreEncryptionKey key = (KeystoreEncryptionKey)o;
+
+ return Objects.equals(k, key.k) &&
+ Arrays.equals(digest, key.digest);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int result = Objects.hash(k);
+
+ result = 31 * result + Arrays.hashCode(digest);
+
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java
new file mode 100644
index 0000000..beba015
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java
@@ -0,0 +1,501 @@
+/*
+ * 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.ignite.spi.encryption.keystore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.concurrent.ThreadLocalRandom;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.spi.encryption.EncryptionSpi;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.resources.LoggerResource;
+import org.apache.ignite.spi.IgniteSpiAdapter;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.jetbrains.annotations.Nullable;
+
+import static javax.crypto.Cipher.DECRYPT_MODE;
+import static javax.crypto.Cipher.ENCRYPT_MODE;
+
+/**
+ * EncryptionSPI implementation base on JDK provided cipher algorithm implementations.
+ *
+ * @see EncryptionSpi
+ * @see KeystoreEncryptionKey
+ */
+public class KeystoreEncryptionSpi extends IgniteSpiAdapter implements EncryptionSpi {
+ /**
+ * Default key store entry name to store Encryption master key.
+ */
+ public static final String DEFAULT_MASTER_KEY_NAME = "ignite.master.key";
+
+ /**
+ * Algorithm supported by implementation.
+ */
+ public static final String CIPHER_ALGO = "AES";
+
+ /**
+ * Default encryption key size;
+ */
+ public static final int DEFAULT_KEY_SIZE = 256;
+
+ /**
+ * Full name of cipher algorithm.
+ */
+ private static final String AES_WITH_PADDING = "AES/CBC/PKCS5Padding";
+
+ /**
+ * Full name of cipher algorithm without padding.
+ */
+ private static final String AES_WITHOUT_PADDING = "AES/CBC/NoPadding";
+
+ /**
+ * Algorithm used for digest calculation.
+ */
+ private static final String DIGEST_ALGO = "SHA-512";
+
+ /**
+ * Data block size.
+ */
+ private static final int BLOCK_SZ = 16;
+
+ /**
+ * Path to master key store.
+ */
+ private String keyStorePath;
+
+ /**
+ * Key store password.
+ */
+ private char[] keyStorePwd;
+
+ /**
+ * Key size.
+ */
+ private int keySize = DEFAULT_KEY_SIZE;
+
+ /**
+ * Master key name.
+ */
+ private String masterKeyName = DEFAULT_MASTER_KEY_NAME;
+
+ /**
+ * Master key.
+ */
+ private KeystoreEncryptionKey masterKey;
+
+ /** Logger. */
+ @LoggerResource
+ protected IgniteLogger log;
+
+ /** Ignite */
+ @IgniteInstanceResource
+ protected Ignite ignite;
+
+ /** */
+ private ThreadLocal<Cipher> aesWithPadding = ThreadLocal.withInitial(() -> {
+ try {
+ return Cipher.getInstance(AES_WITH_PADDING);
+ }
+ catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new IgniteException(e);
+ }
+ });
+
+ /** */
+ private ThreadLocal<Cipher> aesWithoutPadding = ThreadLocal.withInitial(() -> {
+ try {
+ return Cipher.getInstance(AES_WITHOUT_PADDING);
+ }
+ catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new IgniteException(e);
+ }
+ });
+
+ /** {@inheritDoc} */
+ @Override public void spiStart(@Nullable String igniteInstanceName) throws IgniteSpiException {
+ assertParameter(!F.isEmpty(keyStorePath), "KeyStorePath shouldn't be empty");
+ assertParameter(keyStorePwd != null && keyStorePwd.length > 0,
+ "KeyStorePassword shouldn't be empty");
+
+ try (InputStream keyStoreFile = keyStoreFile()) {
+ assertParameter(keyStoreFile != null, keyStorePath + " doesn't exists!");
+
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+
+ ks.load(keyStoreFile, keyStorePwd);
+
+ if (log != null)
+ log.info("Successfully load keyStore [path=" + keyStorePath + "]");
+
+ masterKey = new KeystoreEncryptionKey(ks.getKey(masterKeyName, keyStorePwd), null);
+ }
+ catch (GeneralSecurityException | IOException e) {
+ throw new IgniteSpiException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void spiStop() throws IgniteSpiException {
+ ensureStarted();
+
+ //empty.
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] masterKeyDigest() {
+ ensureStarted();
+
+ return makeDigest(masterKey.key().getEncoded());
+ }
+
+ /** {@inheritDoc} */
+ @Override public KeystoreEncryptionKey create() throws IgniteException {
+ ensureStarted();
+
+ try {
+ KeyGenerator gen = KeyGenerator.getInstance(CIPHER_ALGO);
+
+ gen.init(keySize);
+
+ SecretKey key = gen.generateKey();
+
+ return new KeystoreEncryptionKey(key, makeDigest(key.getEncoded()));
+ }
+ catch (NoSuchAlgorithmException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void encrypt(ByteBuffer data, Serializable key, ByteBuffer res) {
+ doEncryption(data, aesWithPadding.get(), key, res);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void encryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res) {
+ doEncryption(data, aesWithoutPadding.get(), key, res);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] decrypt(byte[] data, Serializable key) {
+ assert key instanceof KeystoreEncryptionKey;
+
+ ensureStarted();
+
+ try {
+ SecretKeySpec keySpec = new SecretKeySpec(((KeystoreEncryptionKey)key).key().getEncoded(), CIPHER_ALGO);
+
+ Cipher cipher = aesWithPadding.get();
+
+ cipher.init(DECRYPT_MODE, keySpec, new IvParameterSpec(data, 0, cipher.getBlockSize()));
+
+ return cipher.doFinal(data, cipher.getBlockSize(), data.length - cipher.getBlockSize());
+ }
+ catch (InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException |
+ BadPaddingException e) {
+ throw new IgniteSpiException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void decryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res) {
+ assert key instanceof KeystoreEncryptionKey;
+
+ ensureStarted();
+
+ try {
+ SecretKeySpec keySpec = new SecretKeySpec(((KeystoreEncryptionKey)key).key().getEncoded(), CIPHER_ALGO);
+
+ Cipher cipher = aesWithoutPadding.get();
+
+ byte[] iv = new byte[cipher.getBlockSize()];
+
+ data.get(iv);
+
+ cipher.init(DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
+
+ cipher.doFinal(data, res);
+ }
+ catch (InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException |
+ ShortBufferException | BadPaddingException e) {
+ throw new IgniteSpiException(e);
+ }
+ }
+
+ /**
+ * @param data Plain data.
+ * @param cipher Cipher.
+ * @param key Encryption key.
+ */
+ private void doEncryption(ByteBuffer data, Cipher cipher, Serializable key, ByteBuffer res) {
+ assert key instanceof KeystoreEncryptionKey;
+
+ ensureStarted();
+
+ try {
+ SecretKeySpec keySpec = new SecretKeySpec(((KeystoreEncryptionKey)key).key().getEncoded(), CIPHER_ALGO);
+
+ byte[] iv = initVector(cipher);
+
+ res.put(iv);
+
+ cipher.init(ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
+
+ cipher.doFinal(data, res);
+ }
+ catch (ShortBufferException | InvalidAlgorithmParameterException | InvalidKeyException |
+ IllegalBlockSizeException | BadPaddingException e) {
+ throw new IgniteSpiException(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte[] encryptKey(Serializable key) {
+ assert key instanceof KeystoreEncryptionKey;
+
+ byte[] serKey = U.toBytes(key);
+
+ byte[] res = new byte[encryptedSize(serKey.length)];
+
+ encrypt(ByteBuffer.wrap(serKey), masterKey, ByteBuffer.wrap(res));
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public KeystoreEncryptionKey decryptKey(byte[] data) {
+ byte[] serKey = decrypt(data, masterKey);
+
+ KeystoreEncryptionKey key = U.fromBytes(serKey);
+
+ byte[] digest = makeDigest(key.key().getEncoded());
+
+ if (!Arrays.equals(key.digest, digest))
+ throw new IgniteException("Key is broken!");
+
+ return key;
+
+ }
+
+ /** {@inheritDoc} */
+ @Override public int encryptedSize(int dataSize) {
+ return encryptedSize(dataSize, AES_WITH_PADDING);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int encryptedSizeNoPadding(int dataSize) {
+ return encryptedSize(dataSize, AES_WITHOUT_PADDING);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int blockSize() {
+ return BLOCK_SZ;
+ }
+
+ /**
+ * @param dataSize Data size.
+ * @param algo Encryption algorithm
+ * @return Encrypted data size.
+ */
+ private int encryptedSize(int dataSize, String algo) {
+ int cntBlocks;
+
+ switch (algo) {
+ case AES_WITH_PADDING:
+ cntBlocks = 2;
+ break;
+
+ case AES_WITHOUT_PADDING:
+ cntBlocks = 1;
+ break;
+
+ default:
+ throw new IllegalStateException("Unknown algorithm: " + algo);
+ }
+
+ return (dataSize/BLOCK_SZ + cntBlocks)*BLOCK_SZ;
+ }
+
+ /**
+ * Calculates message digest.
+ *
+ * @param msg Message.
+ * @return Digest.
+ */
+ private byte[] makeDigest(byte[] msg) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(DIGEST_ALGO);
+
+ return md.digest(msg);
+ }
+ catch (NoSuchAlgorithmException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ /**
+ * @param cipher Cipher.
+ * @return Init vector for encryption.
+ * @see <a href="https://en.wikipedia.org/wiki/Initialization_vector">Initialization vector</a>
+ */
+ private byte[] initVector(Cipher cipher) {
+ byte[] iv = new byte[cipher.getBlockSize()];
+
+ ThreadLocalRandom.current().nextBytes(iv);
+
+ return iv;
+ }
+
+ /**
+ * {@code keyStorePath} could be absolute path or path to classpath resource.
+ *
+ * @return File for {@code keyStorePath}.
+ */
+ private InputStream keyStoreFile() throws IOException {
+ File abs = new File(keyStorePath);
+
+ if (abs.exists())
+ return new FileInputStream(abs);
+
+ URL clsPthRes = KeystoreEncryptionSpi.class.getClassLoader().getResource(keyStorePath);
+
+ if (clsPthRes != null)
+ return clsPthRes.openStream();
+
+ return null;
+ }
+
+ /**
+ * Ensures spi started.
+ *
+ * @throws IgniteException If spi not started.
+ */
+ private void ensureStarted() throws IgniteException {
+ if (started())
+ return;
+
+ throw new IgniteException("EncryptionSpi is not started!");
+ }
+
+ /**
+ * Gets path to jdk keyStore that stores master key.
+ *
+ * @return Key store path.
+ */
+ public String getKeyStorePath() {
+ return keyStorePath;
+ }
+
+ /**
+ * Sets path to jdk keyStore that stores master key.
+ *
+ * @param keyStorePath Path to JDK KeyStore.
+ */
+ public void setKeyStorePath(String keyStorePath) {
+ assert !F.isEmpty(keyStorePath) : "KeyStore path shouldn't be empty";
+ assert !started() : "Spi already started";
+
+ this.keyStorePath = keyStorePath;
+ }
+
+ /**
+ * Gets key store password.
+ *
+ * @return Key store password.
+ */
+ public char[] getKeyStorePwd() {
+ return keyStorePwd;
+ }
+
+ /**
+ * Sets password to access KeyStore.
+ *
+ * @param keyStorePassword Password for Key Store.
+ */
+ public void setKeyStorePassword(char[] keyStorePassword) {
+ assert keyStorePassword != null && keyStorePassword.length > 0;
+ assert !started() : "Spi already started";
+
+ this.keyStorePwd = keyStorePassword;
+ }
+
+ /**
+ * Gets encryption key size.
+ *
+ * @return Encryption key size.
+ */
+ public int getKeySize() {
+ return keySize;
+ }
+
+ /**
+ * Sets encryption key size.
+ *
+ * @param keySize Key size.
+ */
+ public void setKeySize(int keySize) {
+ assert !started() : "Spi already started";
+
+ this.keySize = keySize;
+ }
+
+ /**
+ * Gets master key name.
+ *
+ * @return Master key name.
+ */
+ public String getMasterKeyName() {
+ return masterKeyName;
+ }
+
+ /**
+ * Sets mater key name.
+ *
+ * @param masterKeyName Master key name.
+ */
+ public void setMasterKeyName(String masterKeyName) {
+ assert !started() : "Spi already started";
+
+ this.masterKeyName = masterKeyName;
+ }
+}