Skip to content

Commit

Permalink
Merge pull request #180 from adorsys/feature/DOC-280
Browse files Browse the repository at this point in the history
Feature/doc 280
  • Loading branch information
electronicpeter authored Oct 25, 2019
2 parents fff1373 + 8634370 commit 60792dd
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package de.adorsys.datasafe.business.impl.e2e;

import de.adorsys.datasafe.business.impl.service.DaggerDefaultDatasafeServices;
import de.adorsys.datasafe.business.impl.service.DefaultDatasafeServices;
import de.adorsys.datasafe.directory.impl.profile.config.DefaultDFSConfig;
import de.adorsys.datasafe.encrypiton.api.types.UserID;
import de.adorsys.datasafe.encrypiton.api.types.encryption.EncryptionConfig;
import de.adorsys.datasafe.encrypiton.api.types.encryption.KeyStoreConfig;
import de.adorsys.datasafe.teststorage.WithStorageProvider;
import de.adorsys.datasafe.types.api.actions.ReadRequest;
import de.adorsys.datasafe.types.api.actions.WriteRequest;
import de.adorsys.datasafe.types.api.types.ReadStorePassword;
import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.shaded.org.apache.commons.lang.time.StopWatch;

import java.io.InputStream;
import java.io.OutputStream;

import static org.assertj.core.api.Assertions.assertThat;

@Slf4j
public class KeyStoreTypeCompareTest extends BaseE2ETest {
private final static int NUMBER_WRITES = 100;
private final static int NUMBER_READS = 100;

@SneakyThrows
@ParameterizedTest
@MethodSource("fsOnly")
void compareKeyStoreTypes(WithStorageProvider.StorageDescriptor descriptor) {
long tUBER = test(descriptor, "johnUber", "UBER");
long tBCFKS = test(descriptor, "johnBCFKS", "BCFKS");
log.info("UBER test took: {}", tUBER);
log.info("BCFKS test took: {}", tBCFKS);
// We make sure, that with BCFKS it does not take longer than three times of UBER
Assertions.assertTrue(tUBER * 3 > tBCFKS);
}


@SneakyThrows
long test(WithStorageProvider.StorageDescriptor descriptor, String userName, String keystoreType) {
init(descriptor, keystoreType);
UserID user = new UserID(userName);
assertThat(profileRetrievalService.userExists(user)).isFalse();
john = registerUser(user.getValue(), ReadKeyPasswordTestFactory.getForString("john"));
assertThat(profileRetrievalService.userExists(user)).isTrue();

String filename = "root.txt";
String content = "affe";

StopWatch timer = new StopWatch();
timer.start();

for (int i = 0; i < NUMBER_WRITES; i++) {
log.debug("write file for the {} time", i);
try (OutputStream os = writeToPrivate
.write(WriteRequest.forDefaultPrivate(john, filename))) {
os.write(content.getBytes());
}
}

for (int i = 0; i < NUMBER_READS; i++) {
log.debug("read file for the {} time", i);
try (InputStream is = readFromPrivate
.read(ReadRequest.forDefaultPrivate(john, filename))) {
assertThat(is).hasContent(content);
}
}

timer.stop();

long diff = timer.getTime();

log.info("TIME TOOK {} MILLISECS", diff);
return diff;
}

private void init(StorageDescriptor descriptor, String keystoreType) {
DefaultDatasafeServices datasafeServices = DaggerDefaultDatasafeServices.builder()
.config(new DefaultDFSConfig(descriptor.getLocation(), new ReadStorePassword("PAZZWORT")))
.encryption(
EncryptionConfig.builder()
.keystore(KeyStoreConfig.builder().type(keystoreType).build())
.build()
)
.storage(descriptor.getStorageService().get())
.build();
initialize(DatasafeServicesProvider.dfsConfig(descriptor.getLocation()), datasafeServices);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
public class DefaultKeyStoreCache implements KeyStoreCache {

private final Map<UserID, List<PublicKeyIDWithPublicKey>> publicKeys;
private final Map<UserID, KeyStore> keystore;
private final UserKeyStoreCache keystore;
private final Map<UserID, KeyStore> storageAccess;

@Inject
Expand All @@ -27,7 +27,7 @@ public DefaultKeyStoreCache(
Map<UserID, KeyStore> keystore,
Map<UserID, KeyStore> storageAccess) {
this.publicKeys = publicKeys;
this.keystore = keystore;
this.keystore = new UserKeyStoreCache(keystore);
this.storageAccess = storageAccess;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private <T extends ResourceLocation<T>> void writeKeystore(UserID forUser, KeySt

private KeyStore keyStore(UserIDAuth forUser) {
return keystoreCache.getKeystore().computeIfAbsent(
forUser.getUserID(),
forUser,
userId -> {
AbsoluteLocation<PrivateResource> location = keystoreLocationWithAccess(forUser);
return genericOper.readKeyStore(forUser, location);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface KeyStoreCache {
/**
* Cache for users' private/secret keys
*/
Map<UserID, KeyStore> getKeystore();
UserKeyStoreCache getKeystore();

/**
* Cache for users' storage access
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package de.adorsys.datasafe.directory.impl.profile.keys;

import de.adorsys.datasafe.encrypiton.api.types.UserID;
import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.Delegate;
import lombok.extern.slf4j.Slf4j;

import java.security.Key;
import java.security.KeyStore;
import java.util.Enumeration;
import java.util.Map;
import java.util.function.Function;

@Slf4j
@AllArgsConstructor
public class UserKeyStoreCache {
@Delegate (excludes = ExcludeComputeIfAbsent.class)
private final Map<UserID, KeyStore> map;


/*
The original Map.computeIfAbsent method must not be called and thus is not provided
by this class! It is task of the DefaultKeyStoreCache to generate a new Uber Key Store
for the cache only. For that the password needed, which is
not provided in this method here, is expected too. See next method.
public KeyStore computeIfAbsent(UserID key, Function<? super UserID, ? extends KeyStore> mappingFunction) {}
*/

/**
* If the keyStore provided is a not a UBER KeyStore, a new UBER KeyStore without a
* ReadStorePassword is created. This store is returned and stored in the map.
*
* @param userIDAuth
* @param mappingFunction
* @return always a UBER KeyStore
*/
public KeyStore computeIfAbsent(UserIDAuth userIDAuth, Function<? super UserID, ? extends KeyStore> mappingFunction) {
if (map.containsKey(userIDAuth.getUserID())) {
return map.get(userIDAuth.getUserID());
}
KeyStore keyStore = mappingFunction.apply(userIDAuth.getUserID());
if (! "UBER".equals(keyStore.getType())) {
keyStore = convertKeyStoreToUberKeyStore(userIDAuth, keyStore);
}
map.put(userIDAuth.getUserID(), keyStore);
return keyStore;

}

/**
* Does the conversion of any keyStore to a UBER KeyStore.
*
* @param currentCredentials
* @param current
* @return
*/
@SneakyThrows
private KeyStore convertKeyStoreToUberKeyStore(UserIDAuth currentCredentials, KeyStore current) {
log.debug("the keystore for user {} is of type {} and will be converted to uber in cache", currentCredentials.getUserID(), current.getType() );

KeyStore newKeystore = KeyStore.getInstance("UBER");
newKeystore.load(null, null);
Enumeration<String> aliases = current.aliases();

while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
Key currentKey = current.getKey(alias, currentCredentials.getReadKeyPassword().getValue());
newKeystore.setKeyEntry(
alias,
currentKey,
currentCredentials.getReadKeyPassword().getValue(),
current.getCertificateChain(alias)
);
}

return newKeystore;
}

private interface ExcludeComputeIfAbsent<K,V> {
KeyStore computeIfAbsent(UserID key, Function<? super UserID, ? extends KeyStore> mappingFunction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ public KeyStore createKeyStore(KeyStoreAuth keyStoreAuth,
public KeyStore updateKeyStoreReadKeyPassword(KeyStore current,
KeyStoreAuth currentCredentials,
KeyStoreAuth newCredentials) {
KeyStore newKeystore = KeyStore.getInstance(current.getType());
newKeystore.load(null, null);
KeyStore newKeystore = KeyStoreServiceImplBaseFunctions.newKeyStore(config);
Enumeration<String> aliases = current.aliases();

while (aliases.hasMoreElements()) {
Expand Down

0 comments on commit 60792dd

Please sign in to comment.