From 0f5a4f48b231de5c3b52cb6c5be88d5591460132 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Tue, 6 Aug 2024 17:27:36 +0100 Subject: [PATCH 01/10] Fix: Ensure paths are securely prefixed with root bucket to prevent arbitrary file write --- .../actions/DefaultInboxActionsModule.java | 6 ++++++ .../inbox/impl/actions/WriteToInboxImpl.java | 14 +++++++++++-- .../api/actions/WriteToInboxImplTest.java | 21 ++++++++++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java index d6778f394..d9b6639a9 100644 --- a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java +++ b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java @@ -2,6 +2,7 @@ import dagger.Binds; import dagger.Module; +import dagger.Provides; import de.adorsys.datasafe.inbox.api.InboxService; import de.adorsys.datasafe.inbox.api.actions.ListInbox; import de.adorsys.datasafe.inbox.api.actions.ReadFromInbox; @@ -35,6 +36,11 @@ public abstract class DefaultInboxActionsModule { /** * By default, writes file into users' INBOX using his public key (no privatespace access required). */ + @Provides + static String provideRootBucket() { + return "datasafe-root"; + } + @Binds abstract WriteToInbox writeInbox(WriteToInboxImplRuntimeDelegatable impl); diff --git a/datasafe-inbox/datasafe-inbox-impl/src/main/java/de/adorsys/datasafe/inbox/impl/actions/WriteToInboxImpl.java b/datasafe-inbox/datasafe-inbox-impl/src/main/java/de/adorsys/datasafe/inbox/impl/actions/WriteToInboxImpl.java index 87ad41a2b..1672b9460 100644 --- a/datasafe-inbox/datasafe-inbox-impl/src/main/java/de/adorsys/datasafe/inbox/impl/actions/WriteToInboxImpl.java +++ b/datasafe-inbox/datasafe-inbox-impl/src/main/java/de/adorsys/datasafe/inbox/impl/actions/WriteToInboxImpl.java @@ -10,10 +10,12 @@ import de.adorsys.datasafe.inbox.api.actions.WriteToInbox; import de.adorsys.datasafe.types.api.actions.WriteInboxRequest; import de.adorsys.datasafe.types.api.context.annotations.RuntimeDelegate; +import de.adorsys.datasafe.types.api.resource.BasePublicResource; import de.adorsys.datasafe.types.api.resource.PublicResource; import javax.inject.Inject; import java.io.OutputStream; +import java.net.URI; import java.util.Set; import java.util.stream.Collectors; @@ -30,14 +32,16 @@ public class WriteToInboxImpl implements WriteToInbox { private final PrivateKeyService privateKeyService; private final ResourceResolver resolver; private final EncryptedDocumentWriteService writer; + private final String rootBucket; @Inject public WriteToInboxImpl(PublicKeyService publicKeyService, PrivateKeyService privateKeyService, ResourceResolver resolver, - EncryptedDocumentWriteService writer) { + EncryptedDocumentWriteService writer, String rootBucket) { this.publicKeyService = publicKeyService; this.privateKeyService = privateKeyService; this.resolver = resolver; this.writer = writer; + this.rootBucket = rootBucket; } /** @@ -47,10 +51,16 @@ public WriteToInboxImpl(PublicKeyService publicKeyService, PrivateKeyService pri */ @Override public OutputStream write(WriteInboxRequest, PublicResource> request) { + URI location = request.getLocation().location().asURI(); + String bucket = rootBucket != null ? rootBucket : ""; + if (!location.getPath().startsWith(bucket)) { + location = URI.create(bucket + "/" + location.getPath()); + } + final URI finalLocation = location; return writer.write( request.getRecipients().stream().collect(Collectors.toMap( publicKeyService::publicKey, - it -> resolver.resolveRelativeToPublicInbox(it, request.getLocation()) + it -> resolver.resolveRelativeToPublicInbox(it, new BasePublicResource(finalLocation)) )), privateKeyService.getKeyPair(request.getOwner()) ); diff --git a/datasafe-inbox/datasafe-inbox-impl/src/test/java/de/adorsys/datasafe/inbox/api/actions/WriteToInboxImplTest.java b/datasafe-inbox/datasafe-inbox-impl/src/test/java/de/adorsys/datasafe/inbox/api/actions/WriteToInboxImplTest.java index 52d2f7395..d53ee94ce 100644 --- a/datasafe-inbox/datasafe-inbox-impl/src/test/java/de/adorsys/datasafe/inbox/api/actions/WriteToInboxImplTest.java +++ b/datasafe-inbox/datasafe-inbox-impl/src/test/java/de/adorsys/datasafe/inbox/api/actions/WriteToInboxImplTest.java @@ -21,13 +21,17 @@ import org.mockito.Mock; import java.io.ByteArrayOutputStream; +import java.io.OutputStream; import java.net.URI; import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.util.Collections; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; class WriteToInboxImplTest extends BaseMockitoTest { @@ -61,8 +65,15 @@ class WriteToInboxImplTest extends BaseMockitoTest { private WriteToInboxImpl inbox; @BeforeEach - void init() { + void init() throws NoSuchAlgorithmException { this.publicKeyWithId = new PublicKeyIDWithPublicKey(new KeyID(""), publicKey); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(2048); + this.senderKeyPair = keyPairGenerator.generateKeyPair(); + String rootBucket = "bucket"; + if (inbox == null) { + inbox = new WriteToInboxImpl(publicKeyService, privateKeyService, resolver, writeService, rootBucket); + } } @Test @@ -73,11 +84,15 @@ void write() { .forDefaultPublic(ownerAuth, Collections.singleton(auth), ABSOLUTE_PATH); when(publicKeyService.publicKey(auth)).thenReturn(publicKeyWithId); when(privateKeyService.getKeyPair(ownerAuth)).thenReturn(senderKeyPair); - when(resolver.resolveRelativeToPublicInbox(auth, request.getLocation())).thenReturn(resource); + when(resolver.resolveRelativeToPublicInbox(any(), any())).thenReturn(resource); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); when(writeService.write(Collections.singletonMap(publicKeyWithId, resource), senderKeyPair)).thenReturn(outputStream); - inbox.write(request).write(BYTES.getBytes()); + if (inbox != null && request != null) { + try (OutputStream stream = inbox.write(request)) { + stream.write(BYTES.getBytes()); + } + } assertThat(outputStream.toByteArray()).contains(BYTES.getBytes()); } From 092025e62c2850790c7f19498c94572bae94e9f2 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Fri, 9 Aug 2024 12:57:55 +0100 Subject: [PATCH 02/10] update: BaseUserOperationsTestWithDefaultDatasafeTest with root bucket --- ...eUserOperationsTestWithDefaultDatasafeTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java index 76273efd5..ddaa12925 100644 --- a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java +++ b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java @@ -136,7 +136,7 @@ void shareWithJane() { } // END_SNIPPET - assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "hello.txt"))) + assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "datasafe-root/hello.txt"))) .hasContent("Hello Jane"); } @@ -162,9 +162,9 @@ void shareWithJaneAndJamie() { } // END_SNIPPET - assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "hello.txt"))) + assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "datasafe-root/hello.txt"))) .hasContent("Hello Jane and Jamie"); - assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jamie, "hello.txt"))) + assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jamie, "datasafe-root/hello.txt"))) .hasContent("Hello Jane and Jamie"); } @@ -230,18 +230,18 @@ void listInbox() { assertThat(johnsInboxFilesInRoot) .extracting(it -> it.getResource().asPrivate().decryptedPath().toASCIIString()) .containsExactlyInAnyOrder( - "home/my/secret.txt", - "home/watch/films.txt" + "datasafe-root/home/my/secret.txt", + "datasafe-root/home/watch/films.txt" ); // Now let's list John's home/watch: List> johnsInboxFilesInWatch = defaultDatasafeServices.inboxService() - .list(ListRequest.forDefaultPrivate(user, "home/watch")).collect(Collectors.toList()); + .list(ListRequest.forDefaultPrivate(user, "datasafe-root/home/watch")).collect(Collectors.toList()); // same files we created assertThat(johnsInboxFilesInWatch) .extracting(it -> it.getResource().asPrivate().decryptedPath().toASCIIString()) .containsExactly( - "home/watch/films.txt" + "datasafe-root/home/watch/films.txt" ); // END_SNIPPET } From 5b1fed55821cf1f25660731d732a063b7b89e756 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Tue, 13 Aug 2024 17:21:10 +0100 Subject: [PATCH 03/10] update: datasafe-business-impl-e2e --- .../impl/e2e/BasicFunctionalityUtf8IT.java | 35 +++++++++++-------- ...asicFunctionalityWithPasswordChangeIT.java | 6 +++- .../impl/e2e/DataTamperingResistanceIT.java | 10 ++++-- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java index 69f5d46d3..8cb80dd42 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java @@ -9,6 +9,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import static de.adorsys.datasafe.business.impl.inbox.actions.DefaultInboxActionsModule_ProvideRootBucketFactory.provideRootBucket; import static org.assertj.core.api.Assertions.assertThat; /** @@ -83,19 +84,21 @@ void listingPrivatePathWithUnicode(WithStorageProvider.StorageDescriptor descrip @ParameterizedTest @MethodSource("allStorages") + // Updated BasicFunctionaltyUT8IT.java void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDescriptor descriptor) { init(descriptor); john = registerUser("john"); jane = registerUser("jane"); - String unicodeMessage = "привет мир!"; - writeDataToInbox(john, jane, " привет/prüfungsdokument=/файл:&? с пробелом.док", unicodeMessage); + String filePath = provideRootBucket() + "/привет/prüfungsdokument=/файл:&? с пробелом.док"; // Updated + + writeDataToInbox(john, jane, filePath, unicodeMessage); String inboxContentJane = readInboxUsingPrivateKey( jane, - BasePrivateResource.forPrivate(" привет/prüfungsdokument=/файл:&? с пробелом.док") + BasePrivateResource.forPrivate(filePath) ); assertThat(inboxContentJane).isEqualTo(unicodeMessage); @@ -108,23 +111,25 @@ void listingInboxPathWithUnicode(WithStorageProvider.StorageDescriptor descripto registerJohnAndJane(); - writeDataToInbox(john, jane, "prüfungsdokument.doc+doc", MESSAGE_ONE); - writeDataToInbox(john, jane, "уровень1/?файл+doc", MESSAGE_ONE); - writeDataToInbox(john, jane, "уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); + String rootBucket = provideRootBucket(); + writeDataToInbox(john, jane, rootBucket + "/prüfungsdokument.doc+doc", MESSAGE_ONE); + writeDataToInbox(john, jane, rootBucket + "/уровень1/?файл+doc", MESSAGE_ONE); + writeDataToInbox(john, jane, rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); - assertInboxSpaceList(jane, "", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, ".", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "", rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/уровень1/?файл+doc", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./", rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/уровень1/?файл+doc", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, ".", rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/уровень1/?файл+doc", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); - assertInboxSpaceList(jane, "./prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); + assertInboxSpaceList(jane, rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/prüfungsdokument.doc+doc"); + assertInboxSpaceList(jane, "./" + rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/prüfungsdokument.doc+doc"); - assertInboxSpaceList(jane, "уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+/", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+/", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); } + private void init(StorageDescriptor descriptor) { DefaultDatasafeServices datasafeServices = DatasafeServicesProvider .defaultDatasafeServices(descriptor.getStorageService().get(), descriptor.getLocation()); diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java index 189128a74..71329abf8 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java @@ -25,6 +25,7 @@ import static de.adorsys.datasafe.business.impl.e2e.Const.MESSAGE_ONE; import static de.adorsys.datasafe.business.impl.e2e.Const.PRIVATE_FILE_PATH; import static de.adorsys.datasafe.business.impl.e2e.Const.SHARED_FILE_PATH; +import static de.adorsys.datasafe.business.impl.inbox.actions.DefaultInboxActionsModule_ProvideRootBucketFactory.provideRootBucket; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -66,7 +67,9 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip UserIDAuth jane = registerUser("jane"); UserIDAuth jamie = registerUser("jamie"); - String multiShareFile = "multishare.txt"; + String rootBucket = provideRootBucket(); // Added + String multiShareFile = rootBucket + "/multishare.txt"; // Updated + multishareFiles(sender, john, jane, jamie, multiShareFile); Stream.of(john, jane, jamie).forEach( @@ -78,6 +81,7 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip ); } + @ParameterizedTest @MethodSource("allStorages") void testWriteToPrivateListPrivateReadPrivateAndSendToAndReadFromInbox( diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java index 65544fe61..d4feed792 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java @@ -31,6 +31,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; +import static de.adorsys.datasafe.business.impl.inbox.actions.DefaultInboxActionsModule_ProvideRootBucketFactory.provideRootBucket; import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -79,11 +80,15 @@ void testPrivateDocumentContentTamperResistance() { } } + // Updated DataTamperingResistanceIT.java @Test @SneakyThrows void testInboxDocumentContentTamperResistance() { + String rootBucket = provideRootBucket(); + String fullFileName = rootBucket + "/" + FILENAME; + try (OutputStream os = writeToInbox.write( - WriteInboxRequest.forDefaultPublic(jane, Collections.singleton(john.getUserID()), FILENAME)) + WriteInboxRequest.forDefaultPublic(jane, Collections.singleton(john.getUserID()), fullFileName)) ) { os.write(FILE_TEXT.getBytes(StandardCharsets.UTF_8)); } @@ -91,13 +96,14 @@ void testInboxDocumentContentTamperResistance() { AbsoluteLocation inboxFile = getFirstFileInInbox(john); tamperFileByReplacingOneByteOfEncryptedMessage(inboxFile); - try (InputStream is = readFromInbox.read(ReadRequest.forDefaultPrivate(john, FILENAME))) { + try (InputStream is = readFromInbox.read(ReadRequest.forDefaultPrivate(john, fullFileName))) { assertThatThrownBy( () -> ByteStreams.copy(is, ByteStreams.nullOutputStream()) ).isInstanceOf(InvalidCipherTextIOException.class).hasCauseInstanceOf(AEADBadTagException.class); } } + @ParameterizedTest(name = "{arguments}") @ValueSource(strings = {FILENAME, DIR_AND_FILENAME, DIR_DIR_AND_FILENAME}) @SneakyThrows From 436e00b91d17f3be7261bc81e555d2e3c838ba83 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Tue, 3 Sep 2024 17:09:39 +0100 Subject: [PATCH 04/10] update: BasicFunctionalityIT --- .../datasafe/business/impl/e2e/BasicFunctionalityIT.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java index 5dad99547..51cbd9f95 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java @@ -203,12 +203,11 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip init(descriptor); UserIDAuth owner = registerUser("owner"); - UserIDAuth john = registerUser("john"); UserIDAuth jane = registerUser("jane"); UserIDAuth jamie = registerUser("jamie"); - String multiShareFile = "multishare.txt"; + String multiShareFile = "datasafe-root/multishare.txt"; // Corrected path with prefix try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic( owner, ImmutableSet.of(john.getUserID(), jane.getUserID(), jamie.getUserID()), @@ -229,12 +228,11 @@ void testMultipleRecipientsSharingLargeChunk(WithStorageProvider.StorageDescript init(descriptor); UserIDAuth owner = registerUser("owner"); - UserIDAuth john = registerUser("john"); UserIDAuth jane = registerUser("jane"); UserIDAuth jamie = registerUser("jamie"); - String multiShareFile = "multishare.txt"; + String multiShareFile = "datasafe-root/multishare.txt"; // Corrected path with prefix byte[] bytes = new byte[LARGE_SIZE]; ThreadLocalRandom.current().nextBytes(bytes); try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic( From 9c1f5a83fef6437f2bdf390aa287a1ba089d4562 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Thu, 5 Sep 2024 18:15:58 +0100 Subject: [PATCH 05/10] update business.impl.e2e --- .../datasafe/business/impl/e2e/BaseE2EIT.java | 16 ++++++++++----- .../impl/e2e/BasicFunctionalityUtf8IT.java | 20 +++++++++---------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java index 7d3acd3eb..8695bfacf 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java @@ -43,6 +43,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -125,7 +126,6 @@ protected void writeDataToInbox(UserIDAuth owner, UserIDAuth auth, String path, stream.write(data.getBytes(UTF_8)); } - log.info("File {} of user {} saved to {}", Obfuscate.secure(data), auth, Obfuscate.secure(path, "/")); } protected AbsoluteLocation getFirstFileInPrivate(UserIDAuth owner) { @@ -241,15 +241,21 @@ protected void assertPrivateSpaceList(UserIDAuth user, String root, String... ex protected void assertInboxSpaceList(UserIDAuth user, String root, String... expected) { List paths; + String prefixedRoot = "datasafe-root/" + root; + try (Stream> ls = - listInbox.list(ListRequest.forDefaultPrivate(user, root)) + listInbox.list(ListRequest.forDefaultPrivate(user, prefixedRoot)) ) { paths = ls - .map(it -> it.getResource().asPrivate().decryptedPath().asString()) - .collect(Collectors.toList()); + .map(it -> it.getResource().asPrivate().decryptedPath().asString()) + .collect(Collectors.toList()); } - assertThat(paths).containsExactlyInAnyOrder(expected); + String[] prefixedExpected = Arrays.stream(expected) + .map(path -> "datasafe-root/" + path) + .toArray(String[]::new); + + assertThat(paths).containsExactlyInAnyOrder(prefixedExpected); } @SneakyThrows diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java index 8cb80dd42..673984691 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java @@ -84,7 +84,7 @@ void listingPrivatePathWithUnicode(WithStorageProvider.StorageDescriptor descrip @ParameterizedTest @MethodSource("allStorages") - // Updated BasicFunctionaltyUT8IT.java + // // Updated BasicFunctionaltyUT8IT.java void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDescriptor descriptor) { init(descriptor); @@ -116,17 +116,17 @@ void listingInboxPathWithUnicode(WithStorageProvider.StorageDescriptor descripto writeDataToInbox(john, jane, rootBucket + "/уровень1/?файл+doc", MESSAGE_ONE); writeDataToInbox(john, jane, rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); - assertInboxSpaceList(jane, "", rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/уровень1/?файл+doc", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./", rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/уровень1/?файл+doc", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, ".", rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/уровень1/?файл+doc", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, ".", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/prüfungsdokument.doc+doc"); - assertInboxSpaceList(jane, "./" + rootBucket + "/prüfungsdokument.doc+doc", rootBucket + "/prüfungsdokument.doc+doc"); + assertInboxSpaceList(jane, rootBucket + "/prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); + assertInboxSpaceList(jane, "./" + rootBucket + "/prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); - assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+/", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+/", rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); } From 4ed2e3c8f77a76ffb3f4b07a73f4aa6b62dae3e9 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Fri, 6 Sep 2024 17:15:21 +0100 Subject: [PATCH 06/10] fix: fix BasicFunctionalityUtf8IT to contain the root bucket --- .../datasafe/business/impl/e2e/BaseE2EIT.java | 9 +++-- .../impl/e2e/BasicFunctionalityUtf8IT.java | 34 ++++++++----------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java index 8695bfacf..0c1bf773e 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java @@ -120,11 +120,16 @@ protected void writeDataToPrivate(UserIDAuth auth, String path, String data) { @SneakyThrows protected void writeDataToInbox(UserIDAuth owner, UserIDAuth auth, String path, String data) { + String fullPath = "datasafe-root/" + path; try (OutputStream stream = writeToInbox.write( - WriteInboxRequest.forDefaultPublic(owner, Collections.singleton(auth.getUserID()), path) + WriteInboxRequest.forDefaultPublic(owner, Collections.singleton(auth.getUserID()), fullPath) )) { - + log.info("Writing data '{}' to path '{}' for user '{}'", data, fullPath, auth.getUserID()); stream.write(data.getBytes(UTF_8)); + log.info("File {} of user {} saved to {}", Obfuscate.secure(data), auth, Obfuscate.secure(fullPath, "/")); + } catch (Exception e) { + log.error("Failed to write data to inbox: {}", e.getMessage()); + throw e; } } diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java index 673984691..22201873b 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java @@ -9,7 +9,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import static de.adorsys.datasafe.business.impl.inbox.actions.DefaultInboxActionsModule_ProvideRootBucketFactory.provideRootBucket; import static org.assertj.core.api.Assertions.assertThat; /** @@ -84,7 +83,6 @@ void listingPrivatePathWithUnicode(WithStorageProvider.StorageDescriptor descrip @ParameterizedTest @MethodSource("allStorages") - // // Updated BasicFunctionaltyUT8IT.java void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDescriptor descriptor) { init(descriptor); @@ -92,13 +90,11 @@ void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDesc jane = registerUser("jane"); String unicodeMessage = "привет мир!"; - String filePath = provideRootBucket() + "/привет/prüfungsdokument=/файл:&? с пробелом.док"; // Updated - - writeDataToInbox(john, jane, filePath, unicodeMessage); + writeDataToInbox(john, jane, " привет/prüfungsdokument=/файл:&? с пробелом.док", unicodeMessage); String inboxContentJane = readInboxUsingPrivateKey( jane, - BasePrivateResource.forPrivate(filePath) + BasePrivateResource.forPrivate(" привет/prüfungsdokument=/файл:&? с пробелом.док") ); assertThat(inboxContentJane).isEqualTo(unicodeMessage); @@ -111,22 +107,22 @@ void listingInboxPathWithUnicode(WithStorageProvider.StorageDescriptor descripto registerJohnAndJane(); - String rootBucket = provideRootBucket(); - writeDataToInbox(john, jane, rootBucket + "/prüfungsdokument.doc+doc", MESSAGE_ONE); - writeDataToInbox(john, jane, rootBucket + "/уровень1/?файл+doc", MESSAGE_ONE); - writeDataToInbox(john, jane, rootBucket + "/уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); + //String rootBucket = provideRootBucket(); + writeDataToInbox(john, jane, "/prüfungsdokument.doc+doc", MESSAGE_ONE); + writeDataToInbox(john, jane, "/уровень1/?файл+doc", MESSAGE_ONE); + writeDataToInbox(john, jane, "/уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); - assertInboxSpaceList(jane, "", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, ".", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, ".", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, rootBucket + "/prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); - assertInboxSpaceList(jane, "./" + rootBucket + "/prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); + assertInboxSpaceList(jane, "prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); + assertInboxSpaceList(jane, "./prüfungsdokument.doc+doc", "prüfungsdokument.doc+doc"); - assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, rootBucket + "/уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); - assertInboxSpaceList(jane, "./" + rootBucket + "/уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./уровень1/уровень 2=+", "уровень1/уровень 2=+/&файл пробел+плюс"); + assertInboxSpaceList(jane, "./уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); } From 400ee522ac3beb4054cc602145379918428bdd25 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Sun, 8 Sep 2024 12:40:21 +0100 Subject: [PATCH 07/10] fix : illegalArgument axception in BasicFuctionalityUtf8IT' --- .../de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java | 3 ++- .../datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java index 0c1bf773e..77b107a54 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java @@ -120,7 +120,8 @@ protected void writeDataToPrivate(UserIDAuth auth, String path, String data) { @SneakyThrows protected void writeDataToInbox(UserIDAuth owner, UserIDAuth auth, String path, String data) { - String fullPath = "datasafe-root/" + path; + String trimmedPath = path.trim(); + String fullPath = "datasafe-root/" + trimmedPath; try (OutputStream stream = writeToInbox.write( WriteInboxRequest.forDefaultPublic(owner, Collections.singleton(auth.getUserID()), fullPath) )) { diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java index 22201873b..4e324f3f6 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java @@ -90,11 +90,12 @@ void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDesc jane = registerUser("jane"); String unicodeMessage = "привет мир!"; - writeDataToInbox(john, jane, " привет/prüfungsdokument=/файл:&? с пробелом.док", unicodeMessage); + String path = " привет/prüfungsdokument=/файл:&? с пробелом.док"; + writeDataToInbox(john, jane, path, unicodeMessage); String inboxContentJane = readInboxUsingPrivateKey( jane, - BasePrivateResource.forPrivate(" привет/prüfungsdokument=/файл:&? с пробелом.док") + BasePrivateResource.forPrivate("datasafe-root/" + path.trim()) ); assertThat(inboxContentJane).isEqualTo(unicodeMessage); From add30e62868c7cdcae42130abb9bc404d1100c42 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Wed, 18 Sep 2024 12:29:03 +0100 Subject: [PATCH 08/10] fix StaticBucketRouter refactor DefaultInboxActionsModule --- .../impl/inbox/actions/DefaultInboxActionsModule.java | 4 ---- .../adorsys/datasafe/storage/impl/s3/StaticBucketRouter.java | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java index d9b6639a9..752ef218c 100644 --- a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java +++ b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java @@ -36,10 +36,6 @@ public abstract class DefaultInboxActionsModule { /** * By default, writes file into users' INBOX using his public key (no privatespace access required). */ - @Provides - static String provideRootBucket() { - return "datasafe-root"; - } @Binds abstract WriteToInbox writeInbox(WriteToInboxImplRuntimeDelegatable impl); diff --git a/datasafe-storage/datasafe-storage-impl-s3/src/main/java/de/adorsys/datasafe/storage/impl/s3/StaticBucketRouter.java b/datasafe-storage/datasafe-storage-impl-s3/src/main/java/de/adorsys/datasafe/storage/impl/s3/StaticBucketRouter.java index 2c43345b5..dd55617c9 100644 --- a/datasafe-storage/datasafe-storage-impl-s3/src/main/java/de/adorsys/datasafe/storage/impl/s3/StaticBucketRouter.java +++ b/datasafe-storage/datasafe-storage-impl-s3/src/main/java/de/adorsys/datasafe/storage/impl/s3/StaticBucketRouter.java @@ -20,10 +20,10 @@ public String resourceKey(AbsoluteLocation resource) { UnaryOperator trimStartingSlash = str -> str.replaceFirst("^/", ""); String resourcePath = trimStartingSlash.apply(resource.location().getRawPath()); - if (bucketName == null || "".equals(bucketName) || !resourcePath.contains(bucketName)) { + if (bucketName == null || "".equals(bucketName) || !resourcePath.startsWith(bucketName)) { return resourcePath; } - return trimStartingSlash.apply(resourcePath.substring(resourcePath.indexOf(bucketName) + bucketName.length())); + return trimStartingSlash.apply(resourcePath.substring(bucketName.length())); } } From 3a13233cad5067f9a73ce2c3d3b22ef7d7cb67d6 Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Wed, 18 Sep 2024 12:31:26 +0100 Subject: [PATCH 09/10] fix StaticBucketRouter refactor DefaultInboxActionsModule --- .../business/impl/inbox/actions/DefaultInboxActionsModule.java | 1 - 1 file changed, 1 deletion(-) diff --git a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java index 752ef218c..4cd21a2ed 100644 --- a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java +++ b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java @@ -2,7 +2,6 @@ import dagger.Binds; import dagger.Module; -import dagger.Provides; import de.adorsys.datasafe.inbox.api.InboxService; import de.adorsys.datasafe.inbox.api.actions.ListInbox; import de.adorsys.datasafe.inbox.api.actions.ReadFromInbox; From bcf45ee9cf646fd1be4ced0a4004491dff28c7aa Mon Sep 17 00:00:00 2001 From: AssahBismarkabah Date: Thu, 19 Sep 2024 14:43:39 +0100 Subject: [PATCH 10/10] fix : path traversal if path contains rootBucket --- .../actions/DefaultInboxActionsModule.java | 3 +- .../impl/service/DefaultDatasafeServices.java | 2 + .../service/VersionedDatasafeServices.java | 2 + .../datasafe/business/impl/e2e/BaseE2EIT.java | 62 ++++++++----------- .../impl/e2e/BasicFunctionalityIT.java | 8 ++- .../impl/e2e/BasicFunctionalityUtf8IT.java | 16 +++-- ...asicFunctionalityWithPasswordChangeIT.java | 8 +-- .../impl/e2e/DataTamperingResistanceIT.java | 12 +--- ...OperationsTestWithDefaultDatasafeTest.java | 16 ++--- 9 files changed, 55 insertions(+), 74 deletions(-) diff --git a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java index 4cd21a2ed..32bc8411d 100644 --- a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java +++ b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/inbox/actions/DefaultInboxActionsModule.java @@ -35,7 +35,6 @@ public abstract class DefaultInboxActionsModule { /** * By default, writes file into users' INBOX using his public key (no privatespace access required). */ - @Binds abstract WriteToInbox writeInbox(WriteToInboxImplRuntimeDelegatable impl); @@ -50,4 +49,4 @@ public abstract class DefaultInboxActionsModule { */ @Binds abstract InboxService inboxService(InboxServiceImplRuntimeDelegatable impl); -} +} \ No newline at end of file diff --git a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/DefaultDatasafeServices.java b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/DefaultDatasafeServices.java index f8c5e1112..4a0d3a432 100644 --- a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/DefaultDatasafeServices.java +++ b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/DefaultDatasafeServices.java @@ -69,6 +69,8 @@ interface Builder { @BindsInstance Builder config(DFSConfig config); + @BindsInstance + Builder rootBucket( String rootBucket); /** * Binds (configures) all storage operations - not necessary to call {@code storageList} after. */ diff --git a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/VersionedDatasafeServices.java b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/VersionedDatasafeServices.java index 10769d54b..b750f7d69 100644 --- a/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/VersionedDatasafeServices.java +++ b/datasafe-business/src/main/java/de/adorsys/datasafe/business/impl/service/VersionedDatasafeServices.java @@ -90,6 +90,8 @@ interface Builder { @BindsInstance Builder storage(StorageService storageService); + @BindsInstance + Builder rootBucket( String rootBucket); /** * Provides class overriding functionality, so that you can disable i.e. path encryption * @param overridesRegistry Map with class-overrides (note: you can override classes that are diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java index 77b107a54..c648cfb08 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BaseE2EIT.java @@ -43,7 +43,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -120,18 +119,13 @@ protected void writeDataToPrivate(UserIDAuth auth, String path, String data) { @SneakyThrows protected void writeDataToInbox(UserIDAuth owner, UserIDAuth auth, String path, String data) { - String trimmedPath = path.trim(); - String fullPath = "datasafe-root/" + trimmedPath; try (OutputStream stream = writeToInbox.write( - WriteInboxRequest.forDefaultPublic(owner, Collections.singleton(auth.getUserID()), fullPath) + WriteInboxRequest.forDefaultPublic(owner, Collections.singleton(auth.getUserID()), path) )) { - log.info("Writing data '{}' to path '{}' for user '{}'", data, fullPath, auth.getUserID()); + stream.write(data.getBytes(UTF_8)); - log.info("File {} of user {} saved to {}", Obfuscate.secure(data), auth, Obfuscate.secure(fullPath, "/")); - } catch (Exception e) { - log.error("Failed to write data to inbox: {}", e.getMessage()); - throw e; } + log.info("File {} of user {} saved to {}", Obfuscate.secure(data), auth, Obfuscate.secure(path, "/")); } protected AbsoluteLocation getFirstFileInPrivate(UserIDAuth owner) { @@ -140,7 +134,7 @@ protected AbsoluteLocation getFirstFileInPrivate(UserIDAuth ow protected List> getAllFilesInPrivate(UserIDAuth owner) { try (Stream> ls = listPrivate.list( - ListRequest.forDefaultPrivate(owner, "./") + ListRequest.forDefaultPrivate(owner, "./") )) { List> files = ls.collect(Collectors.toList()); log.info("{} has {} in PRIVATE", owner.getUserID(), files); @@ -184,7 +178,7 @@ protected AbsoluteLocation getFirstFileInInbox(UserIDAuth inbo protected List> getAllFilesInInbox(UserIDAuth inboxOwner) { try (Stream> ls = listInbox.list( - ListRequest.forDefaultPrivate(inboxOwner, "./") + ListRequest.forDefaultPrivate(inboxOwner, "./") )) { List> files = ls.collect(Collectors.toList()); log.info("{} has {} in INBOX", inboxOwner, files); @@ -200,7 +194,7 @@ protected void registerJohnAndJane() { @SneakyThrows protected void sendToInbox(UserIDAuth from, UserID to, String filename, String data) { try (OutputStream stream = writeToInbox.write( - WriteInboxRequest.forDefaultPublic(from, Collections.singleton(to), "./" + filename) + WriteInboxRequest.forDefaultPublic(from, Collections.singleton(to), "./" + filename) )) { stream.write(data.getBytes()); } @@ -235,11 +229,11 @@ protected UserIDAuth createJohnTestUser(int i) { protected void assertPrivateSpaceList(UserIDAuth user, String root, String... expected) { List paths; try (Stream> ls = - listPrivate.list(ListRequest.forDefaultPrivate(user, root)) + listPrivate.list(ListRequest.forDefaultPrivate(user, root)) ) { paths = ls - .map(it -> it.getResource().asPrivate().decryptedPath().asString()) - .collect(Collectors.toList()); + .map(it -> it.getResource().asPrivate().decryptedPath().asString()) + .collect(Collectors.toList()); } assertThat(paths).containsExactlyInAnyOrder(expected); @@ -247,28 +241,22 @@ protected void assertPrivateSpaceList(UserIDAuth user, String root, String... ex protected void assertInboxSpaceList(UserIDAuth user, String root, String... expected) { List paths; - String prefixedRoot = "datasafe-root/" + root; - try (Stream> ls = - listInbox.list(ListRequest.forDefaultPrivate(user, prefixedRoot)) + listInbox.list(ListRequest.forDefaultPrivate(user, root)) ) { paths = ls .map(it -> it.getResource().asPrivate().decryptedPath().asString()) .collect(Collectors.toList()); } - String[] prefixedExpected = Arrays.stream(expected) - .map(path -> "datasafe-root/" + path) - .toArray(String[]::new); - - assertThat(paths).containsExactlyInAnyOrder(prefixedExpected); + assertThat(paths).containsExactlyInAnyOrder(expected); } @SneakyThrows protected void assertRootDirIsEmpty(WithStorageProvider.StorageDescriptor descriptor) { try (Stream> ls = descriptor.getStorageService().get() - .list( - new AbsoluteLocation<>(BasePrivateResource.forPrivate(descriptor.getLocation()))) + .list( + new AbsoluteLocation<>(BasePrivateResource.forPrivate(descriptor.getLocation()))) ) { assertThat(ls).isEmpty(); } @@ -279,18 +267,18 @@ protected void assertRootDirIsEmpty(WithStorageProvider.StorageDescriptor descri // however we can't remove anything above try (Stream files = Files.walk(Paths.get(descriptor.getLocation().asURI()))) { assertThat(files) - .allMatch(it -> it.toFile().isDirectory()) - .extracting(Path::toUri) - .extracting(it -> descriptor.getLocation().asURI().relativize(it)) - .extracting(URI::toString) - .containsExactlyInAnyOrder( - "", - "users/", - "profiles/", - "profiles/public/", - "profiles/private/" - ); + .allMatch(it -> it.toFile().isDirectory()) + .extracting(Path::toUri) + .extracting(it -> descriptor.getLocation().asURI().relativize(it)) + .extracting(URI::toString) + .containsExactlyInAnyOrder( + "", + "users/", + "profiles/", + "profiles/public/", + "profiles/private/" + ); } } } -} +} \ No newline at end of file diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java index 51cbd9f95..07cfde934 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityIT.java @@ -203,11 +203,12 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip init(descriptor); UserIDAuth owner = registerUser("owner"); + UserIDAuth john = registerUser("john"); UserIDAuth jane = registerUser("jane"); UserIDAuth jamie = registerUser("jamie"); - String multiShareFile = "datasafe-root/multishare.txt"; // Corrected path with prefix + String multiShareFile = "multishare.txt"; try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic( owner, ImmutableSet.of(john.getUserID(), jane.getUserID(), jamie.getUserID()), @@ -228,11 +229,12 @@ void testMultipleRecipientsSharingLargeChunk(WithStorageProvider.StorageDescript init(descriptor); UserIDAuth owner = registerUser("owner"); + UserIDAuth john = registerUser("john"); UserIDAuth jane = registerUser("jane"); UserIDAuth jamie = registerUser("jamie"); - String multiShareFile = "datasafe-root/multishare.txt"; // Corrected path with prefix + String multiShareFile = "multishare.txt"; byte[] bytes = new byte[LARGE_SIZE]; ThreadLocalRandom.current().nextBytes(bytes); try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic( @@ -447,4 +449,4 @@ private static ObjectMapper createMapper() { mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper; } -} +} \ No newline at end of file diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java index 4e324f3f6..bda2682af 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityUtf8IT.java @@ -89,13 +89,13 @@ void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDesc john = registerUser("john"); jane = registerUser("jane"); + String unicodeMessage = "привет мир!"; - String path = " привет/prüfungsdokument=/файл:&? с пробелом.док"; - writeDataToInbox(john, jane, path, unicodeMessage); + writeDataToInbox(john, jane, " привет/prüfungsdokument=/файл:&? с пробелом.док", unicodeMessage); String inboxContentJane = readInboxUsingPrivateKey( jane, - BasePrivateResource.forPrivate("datasafe-root/" + path.trim()) + BasePrivateResource.forPrivate(" привет/prüfungsdokument=/файл:&? с пробелом.док") ); assertThat(inboxContentJane).isEqualTo(unicodeMessage); @@ -108,10 +108,9 @@ void listingInboxPathWithUnicode(WithStorageProvider.StorageDescriptor descripto registerJohnAndJane(); - //String rootBucket = provideRootBucket(); - writeDataToInbox(john, jane, "/prüfungsdokument.doc+doc", MESSAGE_ONE); - writeDataToInbox(john, jane, "/уровень1/?файл+doc", MESSAGE_ONE); - writeDataToInbox(john, jane, "/уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); + writeDataToInbox(john, jane, "prüfungsdokument.doc+doc", MESSAGE_ONE); + writeDataToInbox(john, jane, "уровень1/?файл+doc", MESSAGE_ONE); + writeDataToInbox(john, jane, "уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE); assertInboxSpaceList(jane, "", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); assertInboxSpaceList(jane, "./", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс"); @@ -126,10 +125,9 @@ void listingInboxPathWithUnicode(WithStorageProvider.StorageDescriptor descripto assertInboxSpaceList(jane, "./уровень1/уровень 2=+/", "уровень1/уровень 2=+/&файл пробел+плюс"); } - private void init(StorageDescriptor descriptor) { DefaultDatasafeServices datasafeServices = DatasafeServicesProvider .defaultDatasafeServices(descriptor.getStorageService().get(), descriptor.getLocation()); initialize(DatasafeServicesProvider.dfsConfig(descriptor.getLocation()), datasafeServices); } -} +} \ No newline at end of file diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java index 71329abf8..6f244dca9 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithPasswordChangeIT.java @@ -25,7 +25,6 @@ import static de.adorsys.datasafe.business.impl.e2e.Const.MESSAGE_ONE; import static de.adorsys.datasafe.business.impl.e2e.Const.PRIVATE_FILE_PATH; import static de.adorsys.datasafe.business.impl.e2e.Const.SHARED_FILE_PATH; -import static de.adorsys.datasafe.business.impl.inbox.actions.DefaultInboxActionsModule_ProvideRootBucketFactory.provideRootBucket; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -67,9 +66,7 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip UserIDAuth jane = registerUser("jane"); UserIDAuth jamie = registerUser("jamie"); - String rootBucket = provideRootBucket(); // Added - String multiShareFile = rootBucket + "/multishare.txt"; // Updated - + String multiShareFile = "multishare.txt"; multishareFiles(sender, john, jane, jamie, multiShareFile); Stream.of(john, jane, jamie).forEach( @@ -81,7 +78,6 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip ); } - @ParameterizedTest @MethodSource("allStorages") void testWriteToPrivateListPrivateReadPrivateAndSendToAndReadFromInbox( @@ -219,4 +215,4 @@ private void init(WithStorageProvider.StorageDescriptor descriptor) { .defaultDatasafeServices(descriptor.getStorageService().get(), descriptor.getLocation()); initialize(DatasafeServicesProvider.dfsConfig(descriptor.getLocation()), datasafeServices); } -} +} \ No newline at end of file diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java index d4feed792..526f0376b 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/DataTamperingResistanceIT.java @@ -31,7 +31,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; -import static de.adorsys.datasafe.business.impl.inbox.actions.DefaultInboxActionsModule_ProvideRootBucketFactory.provideRootBucket; import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -80,15 +79,11 @@ void testPrivateDocumentContentTamperResistance() { } } - // Updated DataTamperingResistanceIT.java @Test @SneakyThrows void testInboxDocumentContentTamperResistance() { - String rootBucket = provideRootBucket(); - String fullFileName = rootBucket + "/" + FILENAME; - try (OutputStream os = writeToInbox.write( - WriteInboxRequest.forDefaultPublic(jane, Collections.singleton(john.getUserID()), fullFileName)) + WriteInboxRequest.forDefaultPublic(jane, Collections.singleton(john.getUserID()), FILENAME)) ) { os.write(FILE_TEXT.getBytes(StandardCharsets.UTF_8)); } @@ -96,14 +91,13 @@ void testInboxDocumentContentTamperResistance() { AbsoluteLocation inboxFile = getFirstFileInInbox(john); tamperFileByReplacingOneByteOfEncryptedMessage(inboxFile); - try (InputStream is = readFromInbox.read(ReadRequest.forDefaultPrivate(john, fullFileName))) { + try (InputStream is = readFromInbox.read(ReadRequest.forDefaultPrivate(john, FILENAME))) { assertThatThrownBy( () -> ByteStreams.copy(is, ByteStreams.nullOutputStream()) ).isInstanceOf(InvalidCipherTextIOException.class).hasCauseInstanceOf(AEADBadTagException.class); } } - @ParameterizedTest(name = "{arguments}") @ValueSource(strings = {FILENAME, DIR_AND_FILENAME, DIR_DIR_AND_FILENAME}) @SneakyThrows @@ -185,4 +179,4 @@ private byte randomByte(byte notEqualTo) { return resultArray[0]; } -} +} \ No newline at end of file diff --git a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java index ddaa12925..ccdfeec76 100644 --- a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java +++ b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java @@ -136,7 +136,7 @@ void shareWithJane() { } // END_SNIPPET - assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "datasafe-root/hello.txt"))) + assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "hello.txt"))) .hasContent("Hello Jane"); } @@ -162,9 +162,9 @@ void shareWithJaneAndJamie() { } // END_SNIPPET - assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "datasafe-root/hello.txt"))) + assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jane, "hello.txt"))) .hasContent("Hello Jane and Jamie"); - assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jamie, "datasafe-root/hello.txt"))) + assertThat(defaultDatasafeServices.inboxService().read(ReadRequest.forDefaultPrivate(jamie, "hello.txt"))) .hasContent("Hello Jane and Jamie"); } @@ -230,18 +230,18 @@ void listInbox() { assertThat(johnsInboxFilesInRoot) .extracting(it -> it.getResource().asPrivate().decryptedPath().toASCIIString()) .containsExactlyInAnyOrder( - "datasafe-root/home/my/secret.txt", - "datasafe-root/home/watch/films.txt" + "home/my/secret.txt", + "home/watch/films.txt" ); // Now let's list John's home/watch: List> johnsInboxFilesInWatch = defaultDatasafeServices.inboxService() - .list(ListRequest.forDefaultPrivate(user, "datasafe-root/home/watch")).collect(Collectors.toList()); + .list(ListRequest.forDefaultPrivate(user, "home/watch")).collect(Collectors.toList()); // same files we created assertThat(johnsInboxFilesInWatch) .extracting(it -> it.getResource().asPrivate().decryptedPath().toASCIIString()) .containsExactly( - "datasafe-root/home/watch/films.txt" + "home/watch/films.txt" ); // END_SNIPPET } @@ -316,4 +316,4 @@ private void shareMessage(UserIDAuth fromUser, UserID forUser, String messageNam os.write(message.getBytes(StandardCharsets.UTF_8)); } } -} +} \ No newline at end of file