From 136e775f35cc6f4cae41b3f38b8234a0df7d3c66 Mon Sep 17 00:00:00 2001 From: maxml Date: Fri, 1 Jul 2016 17:06:44 +0300 Subject: [PATCH] app-1231 avoid key generation + test --- .../kaa/client/AbstractKaaClient.java | 48 ++++--- .../kaaproject/kaa/client/BaseKaaClient.java | 10 +- .../java/org/kaaproject/kaa/client/Kaa.java | 18 ++- .../kaa/client/KaaClientProperties.java | 25 ++-- .../client/bootstrap/BootstrapManager.java | 10 +- .../kaa/client/channel/KaaChannelManager.java | 52 +++---- .../channel/failover/FailoverManager.java | 2 +- .../persistence/KaaClientPropertiesState.java | 79 ++++++---- .../client/persistence/KaaClientState.java | 8 +- .../src/templates/BaseKaaClient.java.template | 8 +- .../kaaproject/kaa/client/KaaClientTest.java | 35 +++-- .../KaaClientPropertiesStateTest.java | 136 +++++++++++++++--- .../kaa/client/DesktopKaaClientTest.java | 6 +- 13 files changed, 282 insertions(+), 155 deletions(-) diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/AbstractKaaClient.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/AbstractKaaClient.java index 71642565d2..ba307a2623 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/AbstractKaaClient.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/AbstractKaaClient.java @@ -16,21 +16,11 @@ package org.kaaproject.kaa.client; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; - import org.kaaproject.kaa.client.bootstrap.BootstrapManager; import org.kaaproject.kaa.client.bootstrap.DefaultBootstrapManager; import org.kaaproject.kaa.client.channel.BootstrapTransport; import org.kaaproject.kaa.client.channel.ConfigurationTransport; import org.kaaproject.kaa.client.channel.EventTransport; -import org.kaaproject.kaa.client.channel.failover.FailoverManager; import org.kaaproject.kaa.client.channel.KaaChannelManager; import org.kaaproject.kaa.client.channel.KaaDataChannel; import org.kaaproject.kaa.client.channel.KaaInternalChannelManager; @@ -42,10 +32,11 @@ import org.kaaproject.kaa.client.channel.TransportConnectionInfo; import org.kaaproject.kaa.client.channel.TransportProtocolId; import org.kaaproject.kaa.client.channel.UserTransport; +import org.kaaproject.kaa.client.channel.failover.DefaultFailoverManager; +import org.kaaproject.kaa.client.channel.failover.FailoverManager; import org.kaaproject.kaa.client.channel.failover.strategies.FailoverStrategy; import org.kaaproject.kaa.client.channel.impl.DefaultBootstrapDataProcessor; import org.kaaproject.kaa.client.channel.impl.DefaultChannelManager; -import org.kaaproject.kaa.client.channel.failover.DefaultFailoverManager; import org.kaaproject.kaa.client.channel.impl.DefaultOperationDataProcessor; import org.kaaproject.kaa.client.channel.impl.channels.DefaultBootstrapChannel; import org.kaaproject.kaa.client.channel.impl.channels.DefaultOperationTcpChannel; @@ -101,16 +92,23 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; + /** *

* Abstract class that holds general elements of Kaa library. *

- * *

* This class creates and binds Kaa library modules. Public access to each * module is performed using {@link KaaClient} interface. *

- * *

* Http client ({@link AbstractHttpClient}) is used to provide basic * communication with Bootstrap and Operation servers using HTTP protocol. @@ -118,7 +116,6 @@ * * @author Yaroslav Zeygerman * @author Andrew Shvayka - * * @see KaaClient * @see AbstractHttpClient * @see PersistentStorage @@ -155,7 +152,7 @@ protected enum State { STARTED, PAUSED, STOPPED - }; + } protected volatile State clientState = State.CREATED; @@ -176,8 +173,15 @@ protected void setClientState(State state) { } AbstractKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener) throws IOException, GeneralSecurityException { + this(context, listener, false); + } + + AbstractKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener, boolean isUserKeyStrategy) + throws IOException, GeneralSecurityException { + this.context = context; this.stateListener = listener; + if (context.getProperties() != null) { this.properties = context.getProperties(); } else { @@ -194,7 +198,8 @@ protected void setClientState(State state) { Collections.shuffle(cursor.getValue()); } - kaaClientState = new KaaClientPropertiesState(context.createPersistentStorage(), context.getBase64(), this.properties); + kaaClientState = new KaaClientPropertiesState(context.createPersistentStorage(), context.getBase64(), + properties, isUserKeyStrategy); TransportContext transportContext = buildTransportContext(properties, kaaClientState); @@ -365,7 +370,7 @@ private ExecutorService getLifeCycleExecutor() { @Override public void setProfileContainer(ProfileContainer container) { this.profileManager.setProfileContainer(container); - }; + } @Override public void updateProfile() { @@ -506,16 +511,17 @@ public PublicKey getClientPublicKey() { return kaaClientState.getPublicKey(); } - @Override - public String getEndpointKeyHash() { - return kaaClientState.getEndpointKeyHash().getKeyHash(); - } @Override public PrivateKey getClientPrivateKey() { return kaaClientState.getPrivateKey(); } + @Override + public String getEndpointKeyHash() { + return kaaClientState.getEndpointKeyHash().getKeyHash(); + } + @Override public void setEndpointAccessToken(String token) { endpointRegistrationManager.updateEndpointAccessToken(token); diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/BaseKaaClient.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/BaseKaaClient.java index 86d6c73b4b..c004fbef32 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/BaseKaaClient.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/BaseKaaClient.java @@ -39,8 +39,14 @@ @Generated("BaseKaaClient.java.template") public class BaseKaaClient extends AbstractKaaClient implements KaaClient { - public BaseKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener) throws IOException, GeneralSecurityException { - super(context, listener); + public BaseKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener, boolean isUserKeyStrategy) + throws IOException, GeneralSecurityException { + super(context, listener, isUserKeyStrategy); + } + + public BaseKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener) + throws IOException, GeneralSecurityException { + super(context, listener, false); } @Override diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/Kaa.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/Kaa.java index a39eed84a2..b44bb38232 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/Kaa.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/Kaa.java @@ -16,21 +16,20 @@ package org.kaaproject.kaa.client; -import java.io.IOException; -import java.security.GeneralSecurityException; - import org.kaaproject.kaa.client.exceptions.KaaInvalidConfigurationException; import org.kaaproject.kaa.client.exceptions.KaaRuntimeException; import org.kaaproject.kaa.client.exceptions.KaaUnsupportedPlatformException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.security.GeneralSecurityException; + /** * Creates new Kaa client based on {@link KaaClientPlatformContext platform * context} and optional {@link KaaClientStateListener state listener}. - * - * @author Andrew Shvayka * + * @author Andrew Shvayka */ public class Kaa { private static final Logger LOG = LoggerFactory.getLogger(Kaa.class); @@ -43,14 +42,19 @@ public static KaaClient newClient(KaaClientPlatformContext context) throws KaaRu } public static KaaClient newClient(KaaClientPlatformContext context, KaaClientStateListener listener) throws KaaRuntimeException { + return newClient(context, listener, false); + } + + public static KaaClient newClient(KaaClientPlatformContext context, KaaClientStateListener listener, boolean isUserKeyStrategy) + throws KaaRuntimeException { try { - return new BaseKaaClient(context, listener); + return new BaseKaaClient(context, listener, isUserKeyStrategy); } catch (GeneralSecurityException e) { LOG.error("Failed to create Kaa client", e); throw new KaaUnsupportedPlatformException(e); } catch (IOException e) { LOG.error("Failed to create Kaa client", e); - throw new KaaInvalidConfigurationException(e); + throw new KaaInvalidConfigurationException(e); } } } diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/KaaClientProperties.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/KaaClientProperties.java index b1cae3682d..5cedaaa778 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/KaaClientProperties.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/KaaClientProperties.java @@ -16,6 +16,17 @@ package org.kaaproject.kaa.client; +import org.apache.commons.compress.utils.Charsets; +import org.kaaproject.kaa.client.channel.GenericTransportInfo; +import org.kaaproject.kaa.client.channel.ServerType; +import org.kaaproject.kaa.client.channel.TransportConnectionInfo; +import org.kaaproject.kaa.client.channel.TransportProtocolId; +import org.kaaproject.kaa.client.util.Base64; +import org.kaaproject.kaa.common.endpoint.gen.ProtocolMetaData; +import org.kaaproject.kaa.common.endpoint.gen.ProtocolVersionPair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; @@ -29,17 +40,6 @@ import java.util.Properties; import java.util.concurrent.TimeUnit; -import org.apache.commons.compress.utils.Charsets; -import org.kaaproject.kaa.client.channel.GenericTransportInfo; -import org.kaaproject.kaa.client.channel.TransportConnectionInfo; -import org.kaaproject.kaa.client.channel.ServerType; -import org.kaaproject.kaa.client.channel.TransportProtocolId; -import org.kaaproject.kaa.client.util.Base64; -import org.kaaproject.kaa.common.endpoint.gen.ProtocolMetaData; -import org.kaaproject.kaa.common.endpoint.gen.ProtocolVersionPair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import static org.kaaproject.kaa.client.util.Utils.isBlank; /** @@ -92,7 +92,7 @@ public KaaClientProperties(Properties properties) { private static Properties loadProperties(String propsLocation) throws IOException { Properties properties = null; - String propertiesLocation = isBlank(propsLocation) ? DEFAULT_CLIENT_PROPERTIES : propsLocation; + String propertiesLocation = isBlank(propsLocation) ? DEFAULT_CLIENT_PROPERTIES : propsLocation; if (System.getProperty(KAA_CLIENT_PROPERTIES_FILE) != null) { propertiesLocation = System.getProperty(KAA_CLIENT_PROPERTIES_FILE); } @@ -264,5 +264,4 @@ private static void checkNotBlankProperty(String fileName, String errorMessage) throw new IllegalArgumentException(errorMessage); } } - } diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/bootstrap/BootstrapManager.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/bootstrap/BootstrapManager.java index ecb275885d..7207a9ad3a 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/bootstrap/BootstrapManager.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/bootstrap/BootstrapManager.java @@ -16,26 +16,26 @@ package org.kaaproject.kaa.client.bootstrap; -import java.util.List; - import org.kaaproject.kaa.client.channel.BootstrapTransport; -import org.kaaproject.kaa.client.channel.failover.FailoverManager; import org.kaaproject.kaa.client.channel.KaaInternalChannelManager; import org.kaaproject.kaa.client.channel.TransportProtocolId; +import org.kaaproject.kaa.client.channel.failover.FailoverManager; import org.kaaproject.kaa.client.channel.failover.FailoverStatus; import org.kaaproject.kaa.client.transport.TransportException; import org.kaaproject.kaa.common.endpoint.gen.ProtocolMetaData; +import java.util.List; + /** * Bootstrap manager manages the list of available operation servers. * * @author Yaroslav Zeygerman - * */ public interface BootstrapManager { /** * Receives the latest list of servers from the bootstrap server. + * * @throws TransportException the transport exception */ void receiveOperationsServerList() throws TransportException; @@ -44,6 +44,7 @@ public interface BootstrapManager { * Force switch to the next operations server that support given {@link TransportProtocolId} * * @param transportId of the transport protocol. + * @param status failover status * @see TransportProtocolId */ void useNextOperationsServer(TransportProtocolId transportId, FailoverStatus status); @@ -52,7 +53,6 @@ public interface BootstrapManager { * Update the Channel Manager with endpoint's properties retrieved by its DNS. * * @param accessPointId endpoint's DNS. - * */ void useNextOperationsServerByAccessPointId(int accessPointId); diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/KaaChannelManager.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/KaaChannelManager.java index d421d35670..b997e0445e 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/KaaChannelManager.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/KaaChannelManager.java @@ -16,8 +16,6 @@ package org.kaaproject.kaa.client.channel; -import java.util.List; - import org.kaaproject.kaa.client.channel.failover.FailoverManager; import org.kaaproject.kaa.client.channel.failover.FailoverStatus; import org.kaaproject.kaa.client.channel.impl.channels.DefaultBootstrapChannel; @@ -25,6 +23,8 @@ import org.kaaproject.kaa.client.channel.impl.channels.DefaultOperationsChannel; import org.kaaproject.kaa.common.TransportType; +import java.util.List; + /** * Channel manager establishes/removes channels' links between client and * server.
@@ -32,7 +32,6 @@ * Use this manager to add or remove specific network channel implementation for * client-server communication.
*
- * *

  * {@code
  * class SpecificDataChannel implements KaaDataChannel {...}
@@ -41,7 +40,6 @@
  * kaaClient.getChannelManager().addChannel(dataChannel1);
  * }
  * 
- * * The code above registers new data channel in the KaaChannelManager instance. * This channel will be used by each transport abstraction which is supported by * this channel (See {@link KaaDataChannel#getSupportedTransportTypes()}).
@@ -57,7 +55,6 @@ * {@link TransportType#EVENT}].
* and they are added to {@link #addChannel(KaaDataChannel)} in the following * order:
- * *
  * {
  *     @code
@@ -67,7 +64,6 @@
  *     kaaClient.getChannelManager().addChannel(channelB);
  * }
  * 
- * * then ChannelA instance will be used to receive * {@link TransportType#EVENT} and {@link TransportType#LOGGING} data, but to * transmit only {@link TransportType#LOGGING} data. For @@ -92,7 +88,6 @@ * available server. * * @author Yaroslav Zeygerman - * * @see KaaDataChannel */ public interface KaaChannelManager { @@ -101,44 +96,32 @@ public interface KaaChannelManager { * Updates the manager by setting the channel to the specified * {@link TransportType}. * - * @param transport - * the type of the transport which is going to receive updates - * using the specified channel. - * @param channel - * the channel to be added. + * @param transport the type of the transport which is going to receive updates + * using the specified channel. + * @param channel the channel to be added. * @throws KaaInvalidChannelException the kaa invalid channel exception * @see KaaDataChannel - * */ void setChannel(TransportType transport, KaaDataChannel channel) throws KaaInvalidChannelException; /** * Updates the manager by adding the channel. - * - * @param channel - * the channel to be added. - * @see KaaDataChannel - * */ void addChannel(KaaDataChannel channel); /** * Updates the manager by removing the channel from the manager. * - * @param channel - * the channel to be removed. + * @param channel the channel to be removed. * @see KaaDataChannel - * */ void removeChannel(KaaDataChannel channel); /** * Updates the manager by removing the channel from the manager. * - * @param id - * the channel's id. + * @param id the channel's id. * @see KaaDataChannel - * */ void removeChannel(String id); @@ -147,29 +130,24 @@ public interface KaaChannelManager { * * @return the channels' list. * @see KaaDataChannel - * */ List getChannels(); /** * Retrieves channel by the unique channel id. * - * @param id - * the channel's id. + * @param id the channel's id. * @return channel object. - * * @see KaaDataChannel - * */ KaaDataChannel getChannel(String id); /** * Reports to Channel Manager in case link with server was not established. * - * @param server - * the parameters of server that was not connected. + * @param server the parameters of server that was not connected. + * @param status failover status * @see TransportConnectionInfo - * */ void onServerFailed(TransportConnectionInfo server, FailoverStatus status); @@ -180,26 +158,30 @@ public interface KaaChannelManager { /** * Invoke sync on active channel by specified transport type + * * @param type the type */ void sync(TransportType type); /** * Invoke sync acknowledgement on active channel by specified transport type + * * @param type the type */ void syncAck(TransportType type); /** * Invoke sync acknowledgement on active channel + * * @param type - type that is used to identify active channel */ void syncAll(TransportType type); /** - * Returns information about server that is used for data transfer for specified {@link TransportType} - * @param type - type that is used to identify active channel - * @return TransportConnectionInfo active server + * Returns information about server that is used for data transfer for specified {@link TransportType} + * + * @param type - type that is used to identify active channel + * @return TransportConnectionInfo active server */ TransportConnectionInfo getActiveServer(TransportType type); diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/failover/FailoverManager.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/failover/FailoverManager.java index 9f89fcadf8..0e269ca572 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/failover/FailoverManager.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/channel/failover/FailoverManager.java @@ -28,7 +28,7 @@ public interface FailoverManager { * Needs to be invoked when a server fail occurs. * * @param connectionInfo the connection information of the failed server. - * @param status + * @param status failover status * * * @see org.kaaproject.kaa.client.channel.TransportConnectionInfo diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientPropertiesState.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientPropertiesState.java index 95a4685769..70fa1dcc65 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientPropertiesState.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientPropertiesState.java @@ -16,6 +16,28 @@ package org.kaaproject.kaa.client.persistence; +import org.apache.avro.io.BinaryDecoder; +import org.apache.avro.io.BinaryEncoder; +import org.apache.avro.io.DecoderFactory; +import org.apache.avro.io.EncoderFactory; +import org.apache.avro.specific.SpecificDatumReader; +import org.apache.avro.specific.SpecificDatumWriter; +import org.apache.commons.compress.utils.Charsets; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.kaaproject.kaa.client.KaaClientProperties; +import org.kaaproject.kaa.client.event.EndpointAccessToken; +import org.kaaproject.kaa.client.event.EndpointKeyHash; +import org.kaaproject.kaa.client.exceptions.KaaRuntimeException; +import org.kaaproject.kaa.client.notification.TopicListHashCalculator; +import org.kaaproject.kaa.client.util.Base64; +import org.kaaproject.kaa.common.endpoint.gen.SubscriptionType; +import org.kaaproject.kaa.common.endpoint.gen.Topic; +import org.kaaproject.kaa.common.endpoint.security.KeyUtil; +import org.kaaproject.kaa.common.hash.EndpointObjectHash; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -34,39 +56,20 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.UUID; -import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.avro.io.BinaryDecoder; -import org.apache.avro.io.BinaryEncoder; -import org.apache.avro.io.DecoderFactory; -import org.apache.avro.io.EncoderFactory; -import org.apache.avro.specific.SpecificDatumReader; -import org.apache.avro.specific.SpecificDatumWriter; -import org.apache.commons.compress.utils.Charsets; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.kaaproject.kaa.client.KaaClientProperties; -import org.kaaproject.kaa.client.event.EndpointAccessToken; -import org.kaaproject.kaa.client.event.EndpointKeyHash; -import org.kaaproject.kaa.client.notification.TopicListHashCalculator; -import org.kaaproject.kaa.client.util.Base64; -import org.kaaproject.kaa.common.endpoint.gen.SubscriptionType; -import org.kaaproject.kaa.common.endpoint.gen.Topic; -import org.kaaproject.kaa.common.endpoint.security.KeyUtil; -import org.kaaproject.kaa.common.hash.EndpointObjectHash; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class KaaClientPropertiesState implements KaaClientState { private static final String APP_STATE_SEQ_NUMBER = "APP_STATE_SEQ_NUMBER"; private static final String PROFILE_HASH = "PROFILE_HASH"; private static final String ENDPOINT_ACCESS_TOKEN = "ENDPOINT_TOKEN"; - /** The Constant LOG. */ + /** + * The Constant LOG. + */ private static final Logger LOG = LoggerFactory.getLogger(KaaClientPropertiesState.class); private static final String ATTACHED_ENDPOINTS = "attached_eps"; @@ -100,10 +103,19 @@ public class KaaClientPropertiesState implements KaaClientState { private boolean isConfigVersionUpdated = false; private boolean hasUpdate = false; + private boolean isUserKeyStrategy; + public KaaClientPropertiesState(PersistentStorage storage, Base64 base64, KaaClientProperties properties) { + this(storage, base64, properties, false); + } + + public KaaClientPropertiesState(PersistentStorage storage, Base64 base64, KaaClientProperties properties, + boolean isUserKeyStrategy) { + super(); this.storage = storage; this.base64 = base64; + this.isUserKeyStrategy = isUserKeyStrategy; properties.setBase64(base64); @@ -166,6 +178,7 @@ public KaaClientPropertiesState(PersistentStorage storage, Base64 base64, KaaCli topicListHashStr); } } + } catch (Exception e) { LOG.error("Can't load state file", e); } finally { @@ -320,16 +333,16 @@ public String refreshEndpointAccessToken() { } @Override - public PublicKey getPublicKey() { - return getOrInitKeyPair().getPublic(); + public PrivateKey getPrivateKey() { + return getOrInitKeyPair(isUserKeyStrategy).getPrivate(); } @Override - public PrivateKey getPrivateKey() { - return getOrInitKeyPair().getPrivate(); + public PublicKey getPublicKey() { + return getOrInitKeyPair(isUserKeyStrategy).getPublic(); } - private KeyPair getOrInitKeyPair() { + private KeyPair getOrInitKeyPair(boolean isUserKeyStrategy) { LOG.debug("Check if key pair exists {}, {}", clientPublicKeyFileLocation, clientPrivateKeyFileLocation); if (keyPair != null) { return keyPair; @@ -349,6 +362,8 @@ private KeyPair getOrInitKeyPair() { if (!KeyUtil.validateKeyPair(keyPair)) { throw new InvalidKeyException(); } + + return keyPair; } } catch (InvalidKeyException e) { keyPair = null; @@ -361,7 +376,7 @@ private KeyPair getOrInitKeyPair() { IOUtils.closeQuietly(privateKeyInput); } } - if (keyPair == null) { + if (isUserKeyStrategy) { LOG.debug("Generating Client Key pair"); OutputStream privateKeyOutput = null; OutputStream publicKeyOutput = null; @@ -376,6 +391,9 @@ private KeyPair getOrInitKeyPair() { IOUtils.closeQuietly(privateKeyOutput); IOUtils.closeQuietly(publicKeyOutput); } + } else { + LOG.debug("Error loading key pair!", "Key pair is not found and key strategy is default"); + throw new KaaRuntimeException("Key pair is not found and your key strategy is default"); } return keyPair; } @@ -383,7 +401,7 @@ private KeyPair getOrInitKeyPair() { @Override public EndpointKeyHash getEndpointKeyHash() { if (keyHash == null) { - EndpointObjectHash publicKeyHash = EndpointObjectHash.fromSHA1(getOrInitKeyPair().getPublic().getEncoded()); + EndpointObjectHash publicKeyHash = EndpointObjectHash.fromSHA1(getOrInitKeyPair(false).getPublic().getEncoded()); keyHash = new EndpointKeyHash(new String(base64.encodeBase64(publicKeyHash.getData()))); } return keyHash; @@ -551,6 +569,7 @@ public void clean() { setIfNeedProfileResync(false); saveFileDelete(stateFileLocation); saveFileDelete(stateFileLocation + "_bckp"); + keyPair = null; hasUpdate = true; } diff --git a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientState.java b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientState.java index 67da04eb63..7ce346bc00 100644 --- a/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientState.java +++ b/client/client-multi/client-java-core/src/main/java/org/kaaproject/kaa/client/persistence/KaaClientState.java @@ -23,6 +23,7 @@ import org.kaaproject.kaa.client.event.EndpointAccessToken; import org.kaaproject.kaa.client.event.EndpointKeyHash; +import org.kaaproject.kaa.client.exceptions.KaaException; import org.kaaproject.kaa.common.endpoint.gen.Topic; import org.kaaproject.kaa.common.hash.EndpointObjectHash; @@ -31,6 +32,11 @@ public interface KaaClientState { boolean isRegistered(); void setRegistered(boolean registered); + /** + * User can choose to create key pair or not. In default case there is no key generation + * + * @return keys + */ PrivateKey getPrivateKey(); PublicKey getPublicKey(); @@ -50,7 +56,7 @@ public interface KaaClientState { void addTopicSubscription(Long topicId); void removeTopicSubscription(Long topicId); boolean updateTopicSubscriptionInfo(Long topicId, Integer sequenceNumber); - + void setTopicListHash(Integer topicListHash); Integer getTopicListHash(); diff --git a/client/client-multi/client-java-core/src/templates/BaseKaaClient.java.template b/client/client-multi/client-java-core/src/templates/BaseKaaClient.java.template index dd77049b7a..82e5f1fd49 100644 --- a/client/client-multi/client-java-core/src/templates/BaseKaaClient.java.template +++ b/client/client-multi/client-java-core/src/templates/BaseKaaClient.java.template @@ -41,9 +41,15 @@ import ${log_record_class_package}.${log_record_class}; public class BaseKaaClient extends AbstractKaaClient implements KaaClient { public BaseKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener) throws IOException, GeneralSecurityException { - super(context, listener); + super(context, listener, false); } + public BaseKaaClient(KaaClientPlatformContext context, KaaClientStateListener listener, boolean isUserKeyStrategy) + throws IOException, GeneralSecurityException { + super(context, listener, isUserKeyStrategy); + } + + @Override public RecordFuture addLogRecord(${log_record_class} record) { checkClientState(State.STARTED, "Kaa client is not started"); diff --git a/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/KaaClientTest.java b/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/KaaClientTest.java index a599765642..267ef2e35b 100644 --- a/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/KaaClientTest.java +++ b/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/KaaClientTest.java @@ -16,17 +16,6 @@ package org.kaaproject.kaa.client; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.junit.Before; import org.junit.Test; import org.kaaproject.kaa.client.bootstrap.DefaultBootstrapManager; @@ -47,7 +36,6 @@ import org.kaaproject.kaa.client.exceptions.KaaRuntimeException; import org.kaaproject.kaa.client.exceptions.KaaUnsupportedPlatformException; import org.kaaproject.kaa.client.logging.AbstractLogCollector; -import org.kaaproject.kaa.client.persistence.KaaClientPropertiesState; import org.kaaproject.kaa.client.persistence.KaaClientState; import org.kaaproject.kaa.client.persistence.PersistentStorage; import org.kaaproject.kaa.client.profile.ProfileContainer; @@ -62,6 +50,17 @@ import org.mockito.Mockito; import org.springframework.test.util.ReflectionTestUtils; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class KaaClientTest { private KaaClientPlatformContext platformContext; @@ -90,7 +89,7 @@ public void beforeTest() throws Exception { initStorageMock(storage); bsManagerMock = Mockito.mock(DefaultBootstrapManager.class); - client = new AbstractKaaClient(platformContext, stateListener) { + client = new AbstractKaaClient(platformContext, stateListener, true) { @Override protected DefaultBootstrapManager buildBootstrapManager(KaaClientProperties properties, KaaClientState kaaClientState, @@ -107,6 +106,16 @@ public EmptyData getProfile() { }); } + @Test(expected = KaaRuntimeException.class) + public void initKaaClientDefaultKeyStrategy() { + KaaClient client = Kaa.newClient(platformContext, stateListener); + } + + @Test + public void initKaaClientUserStrategy() { + KaaClient client = Kaa.newClient(platformContext, stateListener, true); + } + @Test public void basicLifeCycleTest() throws Exception { client.start(); diff --git a/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/persistance/KaaClientPropertiesStateTest.java b/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/persistance/KaaClientPropertiesStateTest.java index 8d9952c424..6a3e569390 100644 --- a/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/persistance/KaaClientPropertiesStateTest.java +++ b/client/client-multi/client-java-core/src/test/java/org/kaaproject/kaa/client/persistance/KaaClientPropertiesStateTest.java @@ -16,30 +16,40 @@ package org.kaaproject.kaa.client.persistance; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.kaaproject.kaa.client.KaaClientProperties; +import org.kaaproject.kaa.client.exceptions.KaaRuntimeException; import org.kaaproject.kaa.client.persistence.FilePersistentStorage; import org.kaaproject.kaa.client.persistence.KaaClientPropertiesState; import org.kaaproject.kaa.client.persistence.KaaClientState; +import org.kaaproject.kaa.client.persistence.PersistentStorage; import org.kaaproject.kaa.client.util.CommonsBase64; import org.kaaproject.kaa.common.endpoint.gen.SubscriptionType; import org.kaaproject.kaa.common.endpoint.gen.Topic; import org.kaaproject.kaa.common.endpoint.security.KeyUtil; import org.kaaproject.kaa.common.hash.EndpointObjectHash; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + public class KaaClientPropertiesStateTest { private static final String WORK_DIR = "work_dir" + System.getProperty("file.separator"); @@ -69,25 +79,105 @@ public static KaaClientProperties getProperties() throws IOException { return props; } + @Test(expected = KaaRuntimeException.class) + public void testInitKeys() throws IOException, InvalidKeyException { + KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), + getProperties()); + + assertNull(state.getPrivateKey()); + assertNull(state.getPublicKey()); + } + @Test - public void testKeys() throws Exception { - KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), getProperties()); + public void testGenerateKeys() throws IOException, InvalidKeyException { + KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), + getProperties(), true); + + assertNotNull(state.getPrivateKey()); + assertNotNull(state.getPublicKey()); + } + + @Test + public void testDefaultStrategyKeys() throws IOException, InvalidKeyException, NoSuchAlgorithmException { + KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), + getProperties()); + + PersistentStorage storage = new FilePersistentStorage(); + String clientPrivateKeyFileLocation = getProperties().getPrivateKeyFileFullName(); + String clientPublicKeyFileLocation = getProperties().getPublicKeyFileFullName(); + + OutputStream privateKeyOutput = storage.openForWrite(clientPrivateKeyFileLocation); + OutputStream publicKeyOutput = storage.openForWrite(clientPublicKeyFileLocation); + KeyPair keyPair = KeyUtil.generateKeyPair(privateKeyOutput, publicKeyOutput); + + assertArrayEquals(keyPair.getPrivate().getEncoded(), state.getPrivateKey().getEncoded()); + assertArrayEquals(keyPair.getPublic().getEncoded(), state.getPublicKey().getEncoded()); + + //clean + new File(WORK_DIR + KEY_PUBLIC).delete(); + new File(WORK_DIR + KEY_PRIVATE).delete(); + } + + @Test(expected = KaaRuntimeException.class) + public void testDefaultStrategyRecreateKeys() throws IOException, InvalidKeyException, NoSuchAlgorithmException { + KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), + getProperties()); + + PersistentStorage storage = new FilePersistentStorage(); + String clientPrivateKeyFileLocation = getProperties().getPrivateKeyFileFullName(); + String clientPublicKeyFileLocation = getProperties().getPublicKeyFileFullName(); + + OutputStream privateKeyOutput = storage.openForWrite(clientPrivateKeyFileLocation); + OutputStream publicKeyOutput = storage.openForWrite(clientPublicKeyFileLocation); + KeyPair keyPair = KeyUtil.generateKeyPair(privateKeyOutput, publicKeyOutput); + + assertArrayEquals(keyPair.getPrivate().getEncoded(), state.getPrivateKey().getEncoded()); + assertArrayEquals(keyPair.getPublic().getEncoded(), state.getPublicKey().getEncoded()); + + File pub = new File(WORK_DIR + KEY_PUBLIC); + File priv = new File(WORK_DIR + KEY_PRIVATE); + + //clean + Files.delete(Paths.get(WORK_DIR + KEY_PUBLIC)); + new File(WORK_DIR + KEY_PRIVATE).delete(); + state.clean(); + state.getPublicKey(); state.getPrivateKey(); + } + + @Test(expected = KaaRuntimeException.class) + public void testInitKeys2() throws IOException, InvalidKeyException { + KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), + getProperties()); + + assertNull(state.getPrivateKey()); + assertNull(state.getPublicKey()); + } + + @Test + public void testRecreateKeys() throws IOException, InvalidKeyException { + KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), + getProperties(), true); + + state.getPublicKey(); + state.getPrivateKey(); + File pub = new File(WORK_DIR + KEY_PUBLIC); File priv = new File(WORK_DIR + KEY_PRIVATE); + assertArrayEquals(KeyUtil.getPrivate(priv).getEncoded(), state.getPrivateKey().getEncoded()); assertArrayEquals(KeyUtil.getPublic(pub).getEncoded(), state.getPublicKey().getEncoded()); + pub.delete(); priv.delete(); - state.getPrivateKey(); - state.getPublicKey(); - assertNotNull(state.getPrivateKey().getEncoded()); - assertNotNull(state.getPublicKey().getEncoded()); + + assertNotNull(state.getPublicKey()); + assertNotNull(state.getPrivateKey()); } @Test - public void testProfileHash() throws IOException { + public void testProfileHash() throws IOException { KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), getProperties()); EndpointObjectHash hash = EndpointObjectHash.fromSHA1(new byte[]{1, 2, 3}); state.setProfileHash(hash); @@ -95,7 +185,7 @@ public void testProfileHash() throws IOException { } @Test - public void testNfSubscription() throws IOException { + public void testNfSubscription() throws IOException { KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), getProperties()); Topic topic1 = Topic.newBuilder().setId(1234).setName("testName") @@ -120,12 +210,12 @@ public void testNfSubscription() throws IOException { state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), getProperties()); assertEquals(expected, state.getNfSubscriptions()); - + state.addTopicSubscription(topic1.getId()); - + expected.put(topic1.getId(), 0); assertEquals(expected, state.getNfSubscriptions()); - + state.updateTopicSubscriptionInfo(topic1.getId(), 5); expected.put(topic1.getId(), 5); assertEquals(expected, state.getNfSubscriptions()); @@ -178,7 +268,7 @@ public void testConfigVersionUpdates() throws Exception { } @Test - public void testNeedProfileResync() throws Exception{ + public void testNeedProfileResync() throws Exception { KaaClientState state = new KaaClientPropertiesState(new FilePersistentStorage(), CommonsBase64.getInstance(), getProperties()); Assert.assertFalse(state.isNeedProfileResync()); diff --git a/client/client-multi/client-java-desktop/src/test/java/org/kaaproject/kaa/client/DesktopKaaClientTest.java b/client/client-multi/client-java-desktop/src/test/java/org/kaaproject/kaa/client/DesktopKaaClientTest.java index aa1f052d77..63a8b17b52 100644 --- a/client/client-multi/client-java-desktop/src/test/java/org/kaaproject/kaa/client/DesktopKaaClientTest.java +++ b/client/client-multi/client-java-desktop/src/test/java/org/kaaproject/kaa/client/DesktopKaaClientTest.java @@ -47,7 +47,7 @@ public void cleanupBkpFile() { public void testClientInit() throws Exception { System.setProperty(KaaClientProperties.KAA_CLIENT_PROPERTIES_FILE, "client-test.properties"); - KaaClient clientSpy = Mockito.spy(Kaa.newClient(new DesktopKaaPlatformContext(), null)); + KaaClient clientSpy = Mockito.spy(Kaa.newClient(new DesktopKaaPlatformContext(), null, true)); ProfileContainer profileContainerMock = Mockito.mock(ProfileContainer.class); Mockito.when(profileContainerMock.getProfile()).thenReturn(new EmptyData()); @@ -64,7 +64,7 @@ public void testClientInit() throws Exception { @Test public void testClientStartBeforeInit() throws Exception { System.setProperty(KaaClientProperties.KAA_CLIENT_PROPERTIES_FILE, "client-test.properties"); - KaaClient clientSpy = Mockito.spy(Kaa.newClient(new DesktopKaaPlatformContext(), null)); + KaaClient clientSpy = Mockito.spy(Kaa.newClient(new DesktopKaaPlatformContext(), null, true)); ProfileContainer profileContainerMock = Mockito.mock(ProfileContainer.class); Mockito.when(profileContainerMock.getProfile()).thenReturn(new EmptyData()); @@ -79,7 +79,7 @@ public void testClientStartPollAfterInit() throws Exception { System.setProperty(KaaClientProperties.KAA_CLIENT_PROPERTIES_FILE, "client-test.properties"); - KaaClient clientSpy = Mockito.spy(Kaa.newClient(new DesktopKaaPlatformContext(), null)); + KaaClient clientSpy = Mockito.spy(Kaa.newClient(new DesktopKaaPlatformContext(), null, true)); ProfileContainer profileContainerMock = Mockito.mock(ProfileContainer.class); clientSpy.setProfileContainer(profileContainerMock);