-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #180 from adorsys/feature/DOC-280
Feature/doc 280
- Loading branch information
Showing
6 changed files
with
185 additions
and
6 deletions.
There are no files selected for viewing
95 changes: 95 additions & 0 deletions
95
...business/src/test/java/de/adorsys/datasafe/business/impl/e2e/KeyStoreTypeCompareTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
...impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/keys/UserKeyStoreCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters