diff --git a/README.md b/README.md index 176ab845b..721ec1cb6 100644 --- a/README.md +++ b/README.md @@ -281,28 +281,28 @@ TODO: Migrate to AsciiDoc for automatic snippet embedding. ## Generic Datasafe usage First, you want to create Datasafe services. This snippet provides you Datasafe that uses filesystem storage adapter: -[Example:Create Datasafe services](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L46-L53) +[Example:Create Datasafe services](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L46-L52) ```groovy // this will create all Datasafe files and user documents under defaultDatasafeServices = DaggerDefaultDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret")) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .build(); ``` Second you want to add new users: -[Example:Create new user](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L61-L68) +[Example:Create new user](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L60-L67) ```groovy // Creating new user with username 'user' and private/secret key password 'passwrd': /* IMPORTANT: For cases when user profile is stored on S3 without object locks, this requires some global synchronization due to eventual consistency or you need to supply globally unique username on registration */ -defaultDatasafeServices.userProfile().registerUsingDefaults(new UserIDAuth("user", "passwrd")); +defaultDatasafeServices.userProfile().registerUsingDefaults(new UserIDAuth("user", "passwrd"::toCharArray)); ``` After you have a user, he wants to store some data or document securely in his privatespace: -[Example:Store file in privatespace](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L79-L89) +[Example:Store file in privatespace](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L78-L88) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -316,7 +316,7 @@ try (OutputStream os = defaultDatasafeServices.privateService() ``` Now user wants to read again his secured file: -[Example:Read file from privatespace](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L100-L113) +[Example:Read file from privatespace](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L99-L112) ```groovy // creating new user UserIDAuth user = registerUser("jane"); @@ -333,7 +333,7 @@ try (InputStream is = defaultDatasafeServices.privateService() ``` But he doesn't remember the name of file he stored, so he will list all files in privatespace and read first: -[Example:Read file from privatespace using list](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L247-L261) +[Example:Read file from privatespace using list](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L246-L260) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -351,7 +351,7 @@ assertThat(defaultDatasafeServices.privateService().read( ``` Now he wants to share some data with another user: -[Example:Send file to INBOX](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L125-L135) +[Example:Send file to INBOX](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L124-L134) ```groovy // create Jane, so her INBOX does exist UserIDAuth jane = registerUser("jane"); @@ -366,7 +366,7 @@ try (OutputStream os = defaultDatasafeServices.inboxService() Now he wants to share some data with couple of users, so that it will be encrypted once and they both could read the file using each using own private key: -[Example:Send file to INBOX - multiple users](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L147-L159) +[Example:Send file to INBOX - multiple users](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L146-L158) ```groovy // create Jane, so her INBOX does exist UserIDAuth jane = registerUser("jane"); @@ -382,7 +382,7 @@ try (OutputStream os = defaultDatasafeServices.inboxService().write( ``` And finally it is time to read data that was shared with you: -[Example:Read file from INBOX](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L269-L285) +[Example:Read file from INBOX](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithDefaultDatasafeTest.java#L268-L284) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -407,28 +407,28 @@ we can use storage provider that supports versioning. But if we have storage pro (i.e. minio) we can turn-on software versioning, here is its usage examples; First, we will obtain versioned Datasafe services that uses filesystem storage adapter: -[Example:Create versioned Datasafe services](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L47-L54) +[Example:Create versioned Datasafe services](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L47-L53) ```groovy // this will create all Datasafe files and user documents under versionedServices = DaggerVersionedDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret")) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .build(); ``` Next we will create user, this is same as in non-versioned services: -[Example:Creating user for versioned services looks same](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L62-L69) +[Example:Creating user for versioned services looks same](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L61-L68) ```groovy // Creating new user: /* IMPORTANT: For cases when user profile is stored on S3 without object locks, this requires some global synchronization due to eventual consistency or you need to supply globally unique username on registration */ -versionedServices.userProfile().registerUsingDefaults(new UserIDAuth("user", "passwrd")); +versionedServices.userProfile().registerUsingDefaults(new UserIDAuth("user", "passwrd"::toCharArray)); ``` This is how file versioning works when saving file multiple times: -[Example:Saving file couple of times - versioned](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L81-L105) +[Example:Saving file couple of times - versioned](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L80-L104) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -456,7 +456,7 @@ assertThat(versionedServices.latestPrivate().list(ListRequest.forDefaultPrivate( ``` And we can work with file versions too, of course, everything is encrypted: -[Example:Lets check how to read oldest file version](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L107-L123) +[Example:Lets check how to read oldest file version](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L106-L122) ```groovy // so lets collect all versions List, PrivateResource, DFSVersion>> withVersions = @@ -476,7 +476,7 @@ assertThat(versionedServices.privateService() ``` Another important case to mention is how to determine if file has changed on storage compared to some copy we have: -[Example:Check if we have latest file locally](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L133-L164) +[Example:Check if we have latest file locally](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java#L132-L163) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -513,7 +513,7 @@ assertThat(savedOnPC).isAfter(savedOnMobile); ## Datasafe on versioned storage If you have storage for user files on **versioned S3 bucket** and want to get object version when you write object or to read some older version encrypted object, you can follow this example of how to do that: -[Example:Versioned storage support - writing file and reading back](datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java#L138-L173) +[Example:Versioned storage support - writing file and reading back](datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java#L138-L172) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -551,7 +551,7 @@ assertThat(defaultDatasafeServices.privateService().read( ``` Removing old file version can be done by [bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/intro-lifecycle-rules.html#non-current-days-calculations) or manually, using this snippet: -[Example:Versioned storage support - removing specific version](datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java#L189-L216) +[Example:Versioned storage support - removing specific version](datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java#L188-L215) ```groovy // creating new user UserIDAuth user = registerUser("john"); @@ -595,7 +595,7 @@ and it works by putting the custom implementation of a class to be overridden in During runtime, when accessing desired functionality, the library will look into OverridesRegistry for custom class implementation and use it if present. This one has the advantage of not requiring recompilation of Datasafe library, but has a limitation of working on static dependency graph - you can't rebuild it. -[Example:Create overridable Datasafe services without recompilation](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/RuntimeOverrideOperationsTest.java#L31-L54) +[Example:Create overridable Datasafe services without recompilation](datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/RuntimeOverrideOperationsTest.java#L31-L53) ```groovy // This shows how to override path encryption service, in particular we are going to disable it OverridesRegistry registry = new BaseOverridesRegistry(); @@ -606,13 +606,13 @@ PathEncryptionImplRuntimeDelegatable.overrideWith(registry, PathEncryptionImplOv // Customized service, without creating complete module and building it: DefaultDatasafeServices datasafeServices = DaggerDefaultDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret")) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .overridesRegistry(registry) .build(); // registering user -UserIDAuth user = new UserIDAuth("user", "passwrd"); +UserIDAuth user = new UserIDAuth("user", "passwrd"::toCharArray); datasafeServices.userProfile().registerUsingDefaults(user); // writing into user privatespace, note that with default implementation `file.txt` would be encrypted datasafeServices.privateService().write(WriteRequest.forDefaultPrivate(user, "file.txt")); @@ -629,16 +629,16 @@ To create custom Datasafe service we need to follow these 3 steps: 1. Create your own custom module (or modules) - see [CustomPathEncryptionModule](datasafe-examples/datasafe-examples-customize-dagger/src/main/java/de/adorsys/datasafe/examples/business/filesystem/CustomPathEncryptionModule.java) 1. Create custom Datasafe with custom module list - see [CustomlyBuiltDatasafeServices](datasafe-examples/datasafe-examples-customize-dagger/src/main/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServices.java) 1. Use custom-built Datasafe as shown here: -[Example:Create custom-built Datasafe service](datasafe-examples/datasafe-examples-customize-dagger/src/test/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServiceTest.java#L25-L40) +[Example:Create custom-built Datasafe service](datasafe-examples/datasafe-examples-customize-dagger/src/test/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServiceTest.java#L25-L39) ```groovy // Customized service, we create required module using compile time DI provided by Dagger: CustomlyBuiltDatasafeServices datasafeServices = DaggerCustomlyBuiltDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret")) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .build(); // registering user -UserIDAuth user = new UserIDAuth("user", "passwrd"); +UserIDAuth user = new UserIDAuth("user", "password"::toCharArray); datasafeServices.userProfile().registerUsingDefaults(user); // writing into user privatespace, note that with default implementation `file.txt` would be encrypted datasafeServices.privateService().write(WriteRequest.forDefaultPrivate(user, "file.txt")); @@ -649,7 +649,7 @@ assertThat(walk(root)).asString().contains("file.txt"); ### Customizing Datasafe to store dynamic and user-provided credentials In case user wants to register storage credentials himself or place keystore within credentials-protected location one can use this example: -[Example:Datasafe with multi-dfs setup](datasafe-examples/datasafe-examples-multidfs/src/test/java/de/adorsys/datasafe/examples/business/s3/MultiDfsWithCredentialsExampleTest.java#L107-L222) +[Example:Datasafe with multi-dfs setup](datasafe-examples/datasafe-examples-multidfs/src/test/java/de/adorsys/datasafe/examples/business/s3/MultiDfsWithCredentialsExampleTest.java#L106-L220) ```groovy String directoryBucketS3Uri = "s3://" + DIRECTORY_BUCKET.getBucketName() + "/"; // static client that will be used to access `directory` bucket: @@ -662,7 +662,7 @@ StorageService directoryStorage = new S3StorageService( OverridesRegistry registry = new BaseOverridesRegistry(); DefaultDatasafeServices multiDfsDatasafe = DaggerDefaultDatasafeServices .builder() - .config(new DFSConfigWithStorageCreds(directoryBucketS3Uri, "PAZZWORT")) + .config(new DFSConfigWithStorageCreds(directoryBucketS3Uri, "PAZZWORT"::toCharArray)) // This storage service will route requests to proper bucket based on URI content: // URI with directoryBucket to `directoryStorage` // URI with filesBucketOne will get dynamically generated S3Storage @@ -703,7 +703,7 @@ BucketAccessServiceImplRuntimeDelegatable.overrideWith( // Depending on path of file - filesBucketOne or filesBucketTwo - requests will be routed to proper bucket. // I.e. path filesBucketOne/path/to/file will end up in `filesBucketOne` with key path/to/file // his profile and access credentials for `filesBucketOne` will be in `configBucket` -UserIDAuth john = new UserIDAuth("john", "secret"); +UserIDAuth john = new UserIDAuth("john", "secret"::toCharArray); // Here, nothing expects John has own storage credentials: multiDfsDatasafe.userProfile().registerUsingDefaults(john); diff --git a/datasafe-business/pom.xml b/datasafe-business/pom.xml index 4f881a554..5e7e2ec41 100644 --- a/datasafe-business/pom.xml +++ b/datasafe-business/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-cli/pom.xml b/datasafe-cli/pom.xml index 2c96b87f9..3ddb78b35 100644 --- a/datasafe-cli/pom.xml +++ b/datasafe-cli/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe - 1.0.0 + 1.0.0.1 datasafe-cli diff --git a/datasafe-directory/datasafe-directory-api/pom.xml b/datasafe-directory/datasafe-directory-api/pom.xml index c047c87f5..99a2e3472 100644 --- a/datasafe-directory/datasafe-directory-api/pom.xml +++ b/datasafe-directory/datasafe-directory-api/pom.xml @@ -3,7 +3,7 @@ de.adorsys datasafe-directory - 1.0.0 + 1.0.0.1 datasafe-directory-api diff --git a/datasafe-directory/datasafe-directory-impl/pom.xml b/datasafe-directory/datasafe-directory-impl/pom.xml index 1e2f8caa2..3c74831d6 100644 --- a/datasafe-directory/datasafe-directory-impl/pom.xml +++ b/datasafe-directory/datasafe-directory-impl/pom.xml @@ -3,7 +3,7 @@ de.adorsys datasafe-directory - 1.0.0 + 1.0.0.1 datasafe-directory-impl diff --git a/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DFSConfigWithStorageCreds.java b/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DFSConfigWithStorageCreds.java index 69647eb2c..ec3369160 100644 --- a/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DFSConfigWithStorageCreds.java +++ b/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DFSConfigWithStorageCreds.java @@ -6,6 +6,7 @@ import de.adorsys.datasafe.types.api.types.ReadStorePassword; import java.net.URI; +import java.util.function.Supplier; public class DFSConfigWithStorageCreds extends DefaultDFSConfig { @@ -26,6 +27,14 @@ public DFSConfigWithStorageCreds(Uri systemRoot, ReadStorePassword systemPasswor super(systemRoot, systemPassword); } + public DFSConfigWithStorageCreds(URI systemRoot, Supplier systemPassword) { + super(systemRoot, systemPassword); + } + + public DFSConfigWithStorageCreds(String systemRoot, Supplier systemPassword) { + super(systemRoot, systemPassword); + } + @Override public CreateUserPrivateProfile defaultPrivateTemplate(UserIDAuth id) { CreateUserPrivateProfile base = super.defaultPrivateTemplate(id); diff --git a/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DefaultDFSConfig.java b/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DefaultDFSConfig.java index 6960010db..ec627f7ce 100644 --- a/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DefaultDFSConfig.java +++ b/datasafe-directory/datasafe-directory-impl/src/main/java/de/adorsys/datasafe/directory/impl/profile/config/DefaultDFSConfig.java @@ -18,6 +18,7 @@ import java.net.URI; import java.util.Collections; +import java.util.function.Supplier; /** * Default DFS folders layout provider, suitable both for s3 and filesystem. @@ -45,6 +46,16 @@ public DefaultDFSConfig(String systemRoot, ReadStorePassword systemPassword) { this(new Uri(systemRoot), systemPassword); } + /** + * @param systemRoot Root location for all files - private files, user profiles, etc. For example you want + * to place everything in datasafe/system directory within storage + * @param systemPassword System password to open keystore + */ + public DefaultDFSConfig(String systemRoot, Supplier systemPassword) { + this(new Uri(systemRoot), new ReadStorePassword(systemPassword)); + } + + /** * @param systemRoot Root location for all files - private files, user profiles, etc. For example you want * to place everything in datasafe/system directory within storage @@ -54,6 +65,15 @@ public DefaultDFSConfig(URI systemRoot, ReadStorePassword systemPassword) { this(new Uri(systemRoot), systemPassword); } + /** + * @param systemRoot Root location for all files - private files, user profiles, etc. For example you want + * to place everything in datasafe/system directory within storage + * @param systemPassword System password to open keystore + */ + public DefaultDFSConfig(URI systemRoot, Supplier systemPassword) { + this(new Uri(systemRoot), new ReadStorePassword(systemPassword)); + } + /** * @param systemRoot Root location for all files - private files, user profiles, etc. For example you want * to place everything in datasafe/system directory within storage diff --git a/datasafe-directory/pom.xml b/datasafe-directory/pom.xml index 0cbf097ab..b2f293e72 100644 --- a/datasafe-directory/pom.xml +++ b/datasafe-directory/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-encryption/datasafe-encryption-api/pom.xml b/datasafe-encryption/datasafe-encryption-api/pom.xml index 4d0d0f3f4..7b4c54606 100644 --- a/datasafe-encryption/datasafe-encryption-api/pom.xml +++ b/datasafe-encryption/datasafe-encryption-api/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-encryption - 1.0.0 + 1.0.0.1 datasafe-encryption-api diff --git a/datasafe-encryption/datasafe-encryption-api/src/main/java/de/adorsys/datasafe/encrypiton/api/types/UserIDAuth.java b/datasafe-encryption/datasafe-encryption-api/src/main/java/de/adorsys/datasafe/encrypiton/api/types/UserIDAuth.java index 93583ff4a..e0e59029f 100644 --- a/datasafe-encryption/datasafe-encryption-api/src/main/java/de/adorsys/datasafe/encrypiton/api/types/UserIDAuth.java +++ b/datasafe-encryption/datasafe-encryption-api/src/main/java/de/adorsys/datasafe/encrypiton/api/types/UserIDAuth.java @@ -5,6 +5,8 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.function.Supplier; + /** * Wrapper that represents username and password. */ @@ -21,6 +23,11 @@ public UserIDAuth(String userID, ReadKeyPassword readKeyPassword) { this.readKeyPassword = readKeyPassword; } + public UserIDAuth(String userID, Supplier readKeyPassword) { + this.userID = new UserID(userID); + this.readKeyPassword = new ReadKeyPassword(readKeyPassword); + } + @Override public String toString() { return "UserIDAuth{" + diff --git a/datasafe-encryption/datasafe-encryption-impl/pom.xml b/datasafe-encryption/datasafe-encryption-impl/pom.xml index 6644952dc..acd1ad796 100644 --- a/datasafe-encryption/datasafe-encryption-impl/pom.xml +++ b/datasafe-encryption/datasafe-encryption-impl/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-encryption - 1.0.0 + 1.0.0.1 datasafe-encryption-impl diff --git a/datasafe-encryption/datasafe-encryption-impl/src/main/java/de/adorsys/datasafe/encrypiton/impl/document/CMSDocumentReadService.java b/datasafe-encryption/datasafe-encryption-impl/src/main/java/de/adorsys/datasafe/encrypiton/impl/document/CMSDocumentReadService.java index 296a84303..b5ac6c8ed 100644 --- a/datasafe-encryption/datasafe-encryption-impl/src/main/java/de/adorsys/datasafe/encrypiton/impl/document/CMSDocumentReadService.java +++ b/datasafe-encryption/datasafe-encryption-impl/src/main/java/de/adorsys/datasafe/encrypiton/impl/document/CMSDocumentReadService.java @@ -16,6 +16,7 @@ import javax.inject.Inject; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.List; /** @@ -55,30 +56,36 @@ public InputStream read(ReadRequest streamsToClose; - @Override public int read(byte[] b, int off, int len) throws IOException { return streamToRead.read(b, off, len); } - @Override public int read() throws IOException { return streamToRead.read(); } - @Override @SneakyThrows public void close() { - super.close(); - streamsToClose.forEach(CloseCoordinatingStream::doClose); + List exceptions = new ArrayList<>(); + try { + super.close(); + } catch (Exception ex) { + exceptions.add(ex); + } + streamsToClose.forEach(it -> doClose(it, exceptions)); + if (!exceptions.isEmpty()) { + throw exceptions.get(0); + } } - @SneakyThrows - private static void doClose(InputStream stream) { - stream.close(); + private static void doClose(InputStream stream, List exceptions) { + try { + stream.close(); + } catch (Exception ex) { + exceptions.add(ex); + } } - } -} + }} diff --git a/datasafe-encryption/pom.xml b/datasafe-encryption/pom.xml index 2ebf73e6b..f2a52bf4b 100644 --- a/datasafe-encryption/pom.xml +++ b/datasafe-encryption/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-examples/datasafe-examples-business/pom.xml b/datasafe-examples/datasafe-examples-business/pom.xml index cbbd9253a..ba9547371 100644 --- a/datasafe-examples/datasafe-examples-business/pom.xml +++ b/datasafe-examples/datasafe-examples-business/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-examples - 1.0.0 + 1.0.0.1 datasafe-examples-business 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 4323caf50..177f6ed2d 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 @@ -13,7 +13,6 @@ import de.adorsys.datasafe.types.api.actions.WriteRequest; import de.adorsys.datasafe.types.api.resource.AbsoluteLocation; import de.adorsys.datasafe.types.api.resource.ResolvedResource; -import de.adorsys.datasafe.types.api.types.ReadStorePassword; import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory; import lombok.SneakyThrows; import org.junit.jupiter.api.BeforeEach; @@ -46,7 +45,7 @@ void createServices(@TempDir Path root) { // BEGIN_SNIPPET:Create Datasafe services // this will create all Datasafe files and user documents under defaultDatasafeServices = DaggerDefaultDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), new ReadStorePassword("secret"))) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .build(); // END_SNIPPET @@ -63,7 +62,7 @@ void registerUser() { IMPORTANT: For cases when user profile is stored on S3 without object locks, this requires some global synchronization due to eventual consistency or you need to supply globally unique username on registration */ - defaultDatasafeServices.userProfile().registerUsingDefaults(new UserIDAuth("user", ReadKeyPasswordTestFactory.getForString("passwrd"))); + defaultDatasafeServices.userProfile().registerUsingDefaults(new UserIDAuth("user", "passwrd"::toCharArray)); // END_SNIPPET assertThat(defaultDatasafeServices.userProfile().userExists(new UserID("user"))); diff --git a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java index 7f082f087..78e64bbb6 100644 --- a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java +++ b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/BaseUserOperationsTestWithVersionedDatasafeTest.java @@ -14,7 +14,6 @@ import de.adorsys.datasafe.types.api.resource.PrivateResource; import de.adorsys.datasafe.types.api.resource.ResolvedResource; import de.adorsys.datasafe.types.api.resource.Versioned; -import de.adorsys.datasafe.types.api.types.ReadStorePassword; import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory; import lombok.SneakyThrows; import org.junit.jupiter.api.BeforeEach; @@ -47,7 +46,7 @@ void createServices(@TempDir Path root) { // BEGIN_SNIPPET:Create versioned Datasafe services // this will create all Datasafe files and user documents under versionedServices = DaggerVersionedDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), new ReadStorePassword("secret"))) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .build(); // END_SNIPPET @@ -64,7 +63,7 @@ void registerUser() { IMPORTANT: For cases when user profile is stored on S3 without object locks, this requires some global synchronization due to eventual consistency or you need to supply globally unique username on registration */ - versionedServices.userProfile().registerUsingDefaults(new UserIDAuth("user", ReadKeyPasswordTestFactory.getForString("passwrd"))); + versionedServices.userProfile().registerUsingDefaults(new UserIDAuth("user", "passwrd"::toCharArray)); // END_SNIPPET assertThat(versionedServices.userProfile().userExists(new UserID("user"))); diff --git a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/RuntimeOverrideOperationsTest.java b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/RuntimeOverrideOperationsTest.java index 73fccdb14..112c805d7 100644 --- a/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/RuntimeOverrideOperationsTest.java +++ b/datasafe-examples/datasafe-examples-business/src/test/java/de/adorsys/datasafe/examples/business/filesystem/RuntimeOverrideOperationsTest.java @@ -11,8 +11,6 @@ import de.adorsys.datasafe.types.api.context.BaseOverridesRegistry; import de.adorsys.datasafe.types.api.context.overrides.OverridesRegistry; import de.adorsys.datasafe.types.api.resource.Uri; -import de.adorsys.datasafe.types.api.types.ReadStorePassword; -import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -38,13 +36,13 @@ void testPathEncryptionOverridden(@TempDir Path root) { // Customized service, without creating complete module and building it: DefaultDatasafeServices datasafeServices = DaggerDefaultDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), new ReadStorePassword("secret"))) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .overridesRegistry(registry) .build(); // registering user - UserIDAuth user = new UserIDAuth("user", ReadKeyPasswordTestFactory.getForString("passwrd")); + UserIDAuth user = new UserIDAuth("user", "passwrd"::toCharArray); datasafeServices.userProfile().registerUsingDefaults(user); // writing into user privatespace, note that with default implementation `file.txt` would be encrypted datasafeServices.privateService().write(WriteRequest.forDefaultPrivate(user, "file.txt")); diff --git a/datasafe-examples/datasafe-examples-customize-dagger/pom.xml b/datasafe-examples/datasafe-examples-customize-dagger/pom.xml index 6a37bd980..5ac5763ad 100644 --- a/datasafe-examples/datasafe-examples-customize-dagger/pom.xml +++ b/datasafe-examples/datasafe-examples-customize-dagger/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-examples - 1.0.0 + 1.0.0.1 datasafe-examples-customize-dagger diff --git a/datasafe-examples/datasafe-examples-customize-dagger/src/test/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServiceTest.java b/datasafe-examples/datasafe-examples-customize-dagger/src/test/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServiceTest.java index 0f2561369..8b6d3061d 100644 --- a/datasafe-examples/datasafe-examples-customize-dagger/src/test/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServiceTest.java +++ b/datasafe-examples/datasafe-examples-customize-dagger/src/test/java/de/adorsys/datasafe/examples/business/filesystem/CustomlyBuiltDatasafeServiceTest.java @@ -4,8 +4,6 @@ import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth; import de.adorsys.datasafe.storage.impl.fs.FileSystemStorageService; 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 org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -25,12 +23,12 @@ void testPathEncryptionOverridden(@TempDir Path root) { // BEGIN_SNIPPET:Create custom-built Datasafe service // Customized service, we create required module using compile time DI provided by Dagger: CustomlyBuiltDatasafeServices datasafeServices = DaggerCustomlyBuiltDatasafeServices.builder() - .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), new ReadStorePassword("secret"))) + .config(new DefaultDFSConfig(root.toAbsolutePath().toUri(), "secret"::toCharArray)) .storage(new FileSystemStorageService(root)) .build(); // registering user - UserIDAuth user = new UserIDAuth("user", ReadKeyPasswordTestFactory.getForString("passwrd")); + UserIDAuth user = new UserIDAuth("user", "password"::toCharArray); datasafeServices.userProfile().registerUsingDefaults(user); // writing into user privatespace, note that with default implementation `file.txt` would be encrypted datasafeServices.privateService().write(WriteRequest.forDefaultPrivate(user, "file.txt")); diff --git a/datasafe-examples/datasafe-examples-multidfs/pom.xml b/datasafe-examples/datasafe-examples-multidfs/pom.xml index 42fbd2b76..ea4c12309 100644 --- a/datasafe-examples/datasafe-examples-multidfs/pom.xml +++ b/datasafe-examples/datasafe-examples-multidfs/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-examples - 1.0.0 + 1.0.0.1 datasafe-examples-multidfs diff --git a/datasafe-examples/datasafe-examples-multidfs/src/test/java/de/adorsys/datasafe/examples/business/s3/MultiDfsWithCredentialsExampleTest.java b/datasafe-examples/datasafe-examples-multidfs/src/test/java/de/adorsys/datasafe/examples/business/s3/MultiDfsWithCredentialsExampleTest.java index b52170399..fde782021 100644 --- a/datasafe-examples/datasafe-examples-multidfs/src/test/java/de/adorsys/datasafe/examples/business/s3/MultiDfsWithCredentialsExampleTest.java +++ b/datasafe-examples/datasafe-examples-multidfs/src/test/java/de/adorsys/datasafe/examples/business/s3/MultiDfsWithCredentialsExampleTest.java @@ -24,9 +24,7 @@ import de.adorsys.datasafe.types.api.resource.AbsoluteLocation; import de.adorsys.datasafe.types.api.resource.BasePrivateResource; import de.adorsys.datasafe.types.api.resource.StorageIdentifier; -import de.adorsys.datasafe.types.api.types.ReadStorePassword; import de.adorsys.datasafe.types.api.utils.ExecutorServiceUtil; -import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory; import lombok.SneakyThrows; import lombok.experimental.Delegate; import lombok.extern.slf4j.Slf4j; @@ -115,7 +113,7 @@ void testMultiUserStorageUserSetup() { OverridesRegistry registry = new BaseOverridesRegistry(); DefaultDatasafeServices multiDfsDatasafe = DaggerDefaultDatasafeServices .builder() - .config(new DFSConfigWithStorageCreds(directoryBucketS3Uri, new ReadStorePassword("PAZZWORT"))) + .config(new DFSConfigWithStorageCreds(directoryBucketS3Uri, "PAZZWORT"::toCharArray)) // This storage service will route requests to proper bucket based on URI content: // URI with directoryBucket to `directoryStorage` // URI with filesBucketOne will get dynamically generated S3Storage @@ -156,8 +154,7 @@ void testMultiUserStorageUserSetup() { // Depending on path of file - filesBucketOne or filesBucketTwo - requests will be routed to proper bucket. // I.e. path filesBucketOne/path/to/file will end up in `filesBucketOne` with key path/to/file // his profile and access credentials for `filesBucketOne` will be in `configBucket` - UserIDAuth john = new UserIDAuth("john", - ReadKeyPasswordTestFactory.getForString("secret")); + UserIDAuth john = new UserIDAuth("john", "secret"::toCharArray); // Here, nothing expects John has own storage credentials: multiDfsDatasafe.userProfile().registerUsingDefaults(john); diff --git a/datasafe-examples/datasafe-examples-versioned-s3/pom.xml b/datasafe-examples/datasafe-examples-versioned-s3/pom.xml index 4cec42ce9..40421fd11 100644 --- a/datasafe-examples/datasafe-examples-versioned-s3/pom.xml +++ b/datasafe-examples/datasafe-examples-versioned-s3/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-examples - 1.0.0 + 1.0.0.1 datasafe-examples-versioned-s3 diff --git a/datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java b/datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java index 9d6ce6379..0f41f74b9 100644 --- a/datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java +++ b/datasafe-examples/datasafe-examples-versioned-s3/src/test/java/de/adorsys/datasafe/examples/business/s3/BaseUserOperationsWithDefaultDatasafeOnVersionedStorageTest.java @@ -19,9 +19,7 @@ import de.adorsys.datasafe.types.api.actions.WriteRequest; import de.adorsys.datasafe.types.api.callback.PhysicalVersionCallback; import de.adorsys.datasafe.types.api.resource.StorageVersion; -import de.adorsys.datasafe.types.api.types.ReadStorePassword; import de.adorsys.datasafe.types.api.utils.ExecutorServiceUtil; -import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.AfterAll; @@ -120,7 +118,7 @@ void init() { // this will create all Datasafe files and user documents under S3 bucket root, we assume that // S3 versioned bucket was already created defaultDatasafeServices = DaggerDefaultDatasafeServices.builder() - .config(new DefaultDFSConfig(cephMappedUrl, new ReadStorePassword("secret"))) + .config(new DefaultDFSConfig(cephMappedUrl, "secret"::toCharArray)) .storage(new S3StorageService( cephS3, VERSIONED_BUCKET_NAME, @@ -231,7 +229,7 @@ private String writeToPrivate(UserIDAuth user, String path, String fileContent) } private UserIDAuth registerUser(String username) { - UserIDAuth creds = new UserIDAuth(username, ReadKeyPasswordTestFactory.getForString("passwrd" + username)); + UserIDAuth creds = new UserIDAuth(username, ("passwrd" + username)::toCharArray); defaultDatasafeServices.userProfile().registerUsingDefaults(creds); return creds; } diff --git a/datasafe-examples/pom.xml b/datasafe-examples/pom.xml index 7e8d8d850..0afc1607b 100644 --- a/datasafe-examples/pom.xml +++ b/datasafe-examples/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-inbox/datasafe-inbox-api/pom.xml b/datasafe-inbox/datasafe-inbox-api/pom.xml index 9086f0c42..fe582a93c 100644 --- a/datasafe-inbox/datasafe-inbox-api/pom.xml +++ b/datasafe-inbox/datasafe-inbox-api/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-inbox - 1.0.0 + 1.0.0.1 datasafe-inbox-api diff --git a/datasafe-inbox/datasafe-inbox-impl/pom.xml b/datasafe-inbox/datasafe-inbox-impl/pom.xml index 1306f2d25..75d687216 100644 --- a/datasafe-inbox/datasafe-inbox-impl/pom.xml +++ b/datasafe-inbox/datasafe-inbox-impl/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-inbox - 1.0.0 + 1.0.0.1 datasafe-inbox-impl diff --git a/datasafe-inbox/pom.xml b/datasafe-inbox/pom.xml index dc8fbd540..f87f01f48 100644 --- a/datasafe-inbox/pom.xml +++ b/datasafe-inbox/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-long-run-tests/datasafe-business-tests-random-actions/pom.xml b/datasafe-long-run-tests/datasafe-business-tests-random-actions/pom.xml index 6441ca1ea..3e24da582 100644 --- a/datasafe-long-run-tests/datasafe-business-tests-random-actions/pom.xml +++ b/datasafe-long-run-tests/datasafe-business-tests-random-actions/pom.xml @@ -5,7 +5,7 @@ datasafe-long-run-tests de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-long-run-tests/pom.xml b/datasafe-long-run-tests/pom.xml index 6c4f39ba6..23f817b41 100644 --- a/datasafe-long-run-tests/pom.xml +++ b/datasafe-long-run-tests/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-metainfo/datasafe-metainfo-version-api/pom.xml b/datasafe-metainfo/datasafe-metainfo-version-api/pom.xml index 7bc482a97..079b84703 100644 --- a/datasafe-metainfo/datasafe-metainfo-version-api/pom.xml +++ b/datasafe-metainfo/datasafe-metainfo-version-api/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-metainfo - 1.0.0 + 1.0.0.1 datasafe-metainfo-version-api diff --git a/datasafe-metainfo/datasafe-metainfo-version-impl/pom.xml b/datasafe-metainfo/datasafe-metainfo-version-impl/pom.xml index 3ceab782e..5a88410e4 100644 --- a/datasafe-metainfo/datasafe-metainfo-version-impl/pom.xml +++ b/datasafe-metainfo/datasafe-metainfo-version-impl/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-metainfo - 1.0.0 + 1.0.0.1 datasafe-metainfo-version-impl diff --git a/datasafe-metainfo/pom.xml b/datasafe-metainfo/pom.xml index 6f569d4d3..134f5bc6f 100644 --- a/datasafe-metainfo/pom.xml +++ b/datasafe-metainfo/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-privatestore/datasafe-privatestore-api/pom.xml b/datasafe-privatestore/datasafe-privatestore-api/pom.xml index ff7c3c6cb..8971142b7 100644 --- a/datasafe-privatestore/datasafe-privatestore-api/pom.xml +++ b/datasafe-privatestore/datasafe-privatestore-api/pom.xml @@ -5,7 +5,7 @@ datasafe-privatestore de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingInputStream.java b/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingInputStream.java index f021dc8bb..415ad358f 100644 --- a/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingInputStream.java +++ b/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingInputStream.java @@ -13,8 +13,9 @@ @RuntimeDelegate public class PasswordClearingInputStream extends InputStream { - @Delegate(types=InputStream.class, excludes = Closeable.class) + @Delegate(types = InputStream.class, excludes = Closeable.class) private final InputStream inputStream; + private final ReadKeyPassword readKeyPassword; @SneakyThrows @@ -23,6 +24,7 @@ public void close() { if (readKeyPassword != null) { readKeyPassword.clear(); } + inputStream.close(); } } diff --git a/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingOutputStream.java b/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingOutputStream.java index 5832d8ea2..51e9ca663 100644 --- a/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingOutputStream.java +++ b/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingOutputStream.java @@ -11,8 +11,9 @@ @AllArgsConstructor public class PasswordClearingOutputStream extends OutputStream { - @Delegate(types=OutputStream.class, excludes = Closeable.class) + @Delegate(types = OutputStream.class, excludes = Closeable.class) private final OutputStream outputStream; + private final ReadKeyPassword readKeyPassword; @SneakyThrows @@ -21,6 +22,7 @@ public void close() { if (readKeyPassword != null) { readKeyPassword.clear(); } + outputStream.close(); } } diff --git a/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingStream.java b/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingStream.java index 94f3f5d23..17558822f 100644 --- a/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingStream.java +++ b/datasafe-privatestore/datasafe-privatestore-api/src/main/java/de/adorsys/datasafe/privatestore/api/PasswordClearingStream.java @@ -11,8 +11,10 @@ @AllArgsConstructor public class PasswordClearingStream implements Stream { + @Delegate(types = LombokGenericStream.class, excludes = Closeable.class) private final Stream stream; + private final ReadKeyPassword readKeyPassword; @SneakyThrows @@ -21,6 +23,7 @@ public void close() { if (readKeyPassword != null) { readKeyPassword.clear(); } + stream.close(); } diff --git a/datasafe-privatestore/datasafe-privatestore-impl/pom.xml b/datasafe-privatestore/datasafe-privatestore-impl/pom.xml index e31950d7b..67230093c 100644 --- a/datasafe-privatestore/datasafe-privatestore-impl/pom.xml +++ b/datasafe-privatestore/datasafe-privatestore-impl/pom.xml @@ -5,7 +5,7 @@ datasafe-privatestore de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-privatestore/pom.xml b/datasafe-privatestore/pom.xml index cf6da1838..b084b77d1 100644 --- a/datasafe-privatestore/pom.xml +++ b/datasafe-privatestore/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-rest-impl/pom.xml b/datasafe-rest-impl/pom.xml index 07198a68a..6d5c9a18d 100644 --- a/datasafe-rest-impl/pom.xml +++ b/datasafe-rest-impl/pom.xml @@ -5,11 +5,11 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 datasafe-rest-impl - 1.0.0 + 1.0.0.1 datasafe-rest-impl Spring Boot DataSafe Application diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java index 86f9b8e6a..a71339935 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java @@ -1,7 +1,12 @@ package de.adorsys.datasafe.rest.impl.security; import com.google.common.base.Strings; -import io.jsonwebtoken.*; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.SignatureException; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationManager; diff --git a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java index 66e1cf947..c115fccf3 100644 --- a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java +++ b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java @@ -10,13 +10,17 @@ import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth; import de.adorsys.datasafe.rest.impl.dto.UserDTO; import de.adorsys.datasafe.types.api.resource.StorageIdentifier; +import de.adorsys.datasafe.types.api.types.ReadKeyPassword; import lombok.SneakyThrows; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -42,6 +46,8 @@ class UserControllerTest extends BaseTokenDatasafeEndpointTest { @MockBean private DFSBasedProfileStorageImpl userProfile; + @Captor + private ArgumentCaptor password; @BeforeEach public void setup() { @@ -92,8 +98,10 @@ void changePasswordTest() { verify(userProfile).updateReadKeyPassword( eq(new UserIDAuth(TEST_USER, TEST_PASS)), - eq(ReadKeyPasswordHelper.getForString(newPassword)) + password.capture() ); + + assertThat(password.getValue().getValue()).isEqualTo(newPassword.toCharArray()); } @SneakyThrows diff --git a/datasafe-runtime-delegate/pom.xml b/datasafe-runtime-delegate/pom.xml index 29025f51b..182be430e 100644 --- a/datasafe-runtime-delegate/pom.xml +++ b/datasafe-runtime-delegate/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe - 1.0.0 + 1.0.0.1 datasafe-runtime-delegate diff --git a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java index c125322a4..de84f7b85 100644 --- a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java +++ b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java @@ -1,6 +1,16 @@ package de.adorsys.datasafe.runtimedelegate; -import com.squareup.javapoet.*; +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeVariableName; import javax.annotation.Generated; import javax.annotation.Nullable; diff --git a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java index 20a0668d7..11643db98 100644 --- a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java +++ b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java @@ -3,10 +3,18 @@ import com.google.auto.service.AutoService; import de.adorsys.datasafe.types.api.context.overrides.OverridesRegistry; -import javax.annotation.processing.*; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; import javax.inject.Inject; import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import java.lang.annotation.Annotation; import java.util.Collections; diff --git a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java index ad1237d68..6dbdba2e3 100644 --- a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java +++ b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java @@ -51,4 +51,4 @@ public SimpleClass.Dependency getDependency() { return dependency; } } -} +} \ No newline at end of file diff --git a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java index dabe499f8..b045c7aee 100644 --- a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java +++ b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java @@ -68,4 +68,4 @@ public SimpleClassWithGeneric.Dependency getDependency() { return dependency; } } -} +} \ No newline at end of file diff --git a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java index 3ec1dd320..77f34e5c9 100644 --- a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java +++ b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java @@ -51,4 +51,4 @@ public SimpleClassWithVoid.Dependency getDependency() { return dependency; } } -} +} \ No newline at end of file diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml b/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml index 87ea7050a..03df4528c 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml +++ b/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml @@ -5,7 +5,7 @@ datasafe-simple-adapter de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-api/src/main/java/de/adorsys/datasafe/simple/adapter/api/types/AmazonS3DFSCredentials.java b/datasafe-simple-adapter/datasafe-simple-adapter-api/src/main/java/de/adorsys/datasafe/simple/adapter/api/types/AmazonS3DFSCredentials.java index 9b3d7e607..f38b5bf5f 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-api/src/main/java/de/adorsys/datasafe/simple/adapter/api/types/AmazonS3DFSCredentials.java +++ b/datasafe-simple-adapter/datasafe-simple-adapter-api/src/main/java/de/adorsys/datasafe/simple/adapter/api/types/AmazonS3DFSCredentials.java @@ -22,8 +22,21 @@ public class AmazonS3DFSCredentials extends DFSCredentials { @Builder.Default private final int queueSize = 5; + // value 0 means, do not set it when creating connection, + // so S3 default is used + @Builder.Default + private final int maxConnections = 0; + + // value 0 means, do not set it when creating connection, + // so S3 default is used + @Builder.Default + private final int requestTimeout = 0; + + public String getContainer() { return rootBucket.split("/")[0]; } + + } diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml b/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml index 616798c08..ee2ed46cf 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml +++ b/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml @@ -5,7 +5,7 @@ datasafe-simple-adapter de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/main/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeServiceImpl.java b/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/main/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeServiceImpl.java index 76f48b897..b21722c34 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/main/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeServiceImpl.java +++ b/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/main/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeServiceImpl.java @@ -16,7 +16,16 @@ import de.adorsys.datasafe.encrypiton.api.types.encryption.MutableEncryptionConfig; import de.adorsys.datasafe.simple.adapter.api.SimpleDatasafeService; import de.adorsys.datasafe.simple.adapter.api.exceptions.SimpleAdapterException; -import de.adorsys.datasafe.simple.adapter.api.types.*; +import de.adorsys.datasafe.simple.adapter.api.types.AmazonS3DFSCredentials; +import de.adorsys.datasafe.simple.adapter.api.types.DFSCredentials; +import de.adorsys.datasafe.simple.adapter.api.types.DFSCredentialsFactory; +import de.adorsys.datasafe.simple.adapter.api.types.DSDocument; +import de.adorsys.datasafe.simple.adapter.api.types.DSDocumentStream; +import de.adorsys.datasafe.simple.adapter.api.types.DocumentContent; +import de.adorsys.datasafe.simple.adapter.api.types.DocumentDirectoryFQN; +import de.adorsys.datasafe.simple.adapter.api.types.DocumentFQN; +import de.adorsys.datasafe.simple.adapter.api.types.FilesystemDFSCredentials; +import de.adorsys.datasafe.simple.adapter.api.types.ListRecursiveFlag; import de.adorsys.datasafe.simple.adapter.impl.pathencryption.SwitchablePathEncryptionImpl; import de.adorsys.datasafe.storage.api.StorageService; import de.adorsys.datasafe.storage.impl.fs.FileSystemStorageService; @@ -72,6 +81,7 @@ public SimpleDatasafeServiceImpl(DFSCredentials dfsCredentials, MutableEncryptio .storage(getStorageService()) .build(); } + public StorageService getStorageService() { return rootAndStorage.getStorageService(); } @@ -199,12 +209,21 @@ private static SystemRootAndStorageService useAmazonS3(AmazonS3DFSCredentials df AmazonS3DFSCredentials amazonS3DFSCredentials = dfsCredentials; LogStringFrame lsf = new LogStringFrame(); lsf.add("AMAZON S3"); - lsf.add("root bucket : " + amazonS3DFSCredentials.getRootBucket()); - lsf.add("url : " + amazonS3DFSCredentials.getUrl()); - lsf.add("region : " + amazonS3DFSCredentials.getRegion()); - lsf.add("path encryption : " + SwitchablePathEncryptionImpl.checkIsPathEncryptionToUse()); - lsf.add("no https : " + amazonS3DFSCredentials.isNoHttps()); - lsf.add("threadpool size : " + amazonS3DFSCredentials.getThreadPoolSize()); + lsf.add("root bucket : " + amazonS3DFSCredentials.getRootBucket()); + lsf.add("url : " + amazonS3DFSCredentials.getUrl()); + lsf.add("region : " + amazonS3DFSCredentials.getRegion()); + lsf.add("path encryption : " + SwitchablePathEncryptionImpl.checkIsPathEncryptionToUse()); + lsf.add("no https : " + amazonS3DFSCredentials.isNoHttps()); + lsf.add("threadpool size : " + amazonS3DFSCredentials.getThreadPoolSize()); + int maxConnections = amazonS3DFSCredentials.getMaxConnections(); + if (maxConnections > 0) { + lsf.add("max connections : " + maxConnections); + } + int requestTimeout = amazonS3DFSCredentials.getRequestTimeout(); + if (requestTimeout > 0) { + lsf.add("request timeout : " + requestTimeout); + } + log.info(lsf.toString()); AmazonS3ClientBuilder amazonS3ClientBuilder = AmazonS3ClientBuilder.standard() .withCredentials( @@ -227,11 +246,21 @@ private static SystemRootAndStorageService useAmazonS3(AmazonS3DFSCredentials df amazonS3ClientBuilder.withRegion(amazonS3DFSCredentials.getRegion()); } - if (amazonS3DFSCredentials.isNoHttps()) { - log.info("Creating S3 client without https"); + if (amazonS3DFSCredentials.isNoHttps() || maxConnections > 0 || requestTimeout > 0) { ClientConfiguration clientConfig = new ClientConfiguration(); - clientConfig.setProtocol(Protocol.HTTP); - clientConfig.disableSocketProxy(); + if (amazonS3DFSCredentials.isNoHttps()) { + log.info("Creating S3 client without https"); + clientConfig.setProtocol(Protocol.HTTP); + clientConfig.disableSocketProxy(); + } + if (maxConnections > 0) { + log.info("Creating S3 client with max connections:{}", maxConnections); + clientConfig.setMaxConnections(maxConnections); + } + if (requestTimeout > 0) { + log.info("Creating S3 client with connection timeout:{}", requestTimeout); + clientConfig.setRequestTimeout(requestTimeout); + } amazonS3ClientBuilder.withClientConfiguration(clientConfig); } diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/test/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeAdapterTest.java b/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/test/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeAdapterTest.java index 814bc61db..99e0e77c4 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/test/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeAdapterTest.java +++ b/datasafe-simple-adapter/datasafe-simple-adapter-impl/src/test/java/de/adorsys/datasafe/simple/adapter/impl/SimpleDatasafeAdapterTest.java @@ -1,10 +1,12 @@ package de.adorsys.datasafe.simple.adapter.impl; import com.amazonaws.services.s3.model.AmazonS3Exception; +import com.sun.management.UnixOperatingSystemMXBean; import de.adorsys.datasafe.encrypiton.api.types.UserID; import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth; import de.adorsys.datasafe.encrypiton.api.types.encryption.MutableEncryptionConfig; import de.adorsys.datasafe.simple.adapter.api.SimpleDatasafeService; +import de.adorsys.datasafe.simple.adapter.api.types.AmazonS3DFSCredentials; import de.adorsys.datasafe.simple.adapter.api.types.DFSCredentials; import de.adorsys.datasafe.simple.adapter.api.types.DSDocument; import de.adorsys.datasafe.simple.adapter.api.types.DSDocumentStream; @@ -21,26 +23,27 @@ import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.implementation.bytecode.Throw; import org.bouncycastle.util.io.Streams; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import java.io.ByteArrayInputStream; import java.io.OutputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; import java.nio.file.NoSuchFileException; import java.security.UnrecoverableKeyException; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import java.util.stream.IntStream; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; @Slf4j class SimpleDatasafeAdapterTest extends WithStorageProvider { @@ -300,6 +303,39 @@ void testTwoUsers(WithStorageProvider.StorageDescriptor descriptor) { } + @ParameterizedTest + @MethodSource("minioOnly") + @SneakyThrows + void testExhaustedInputStream(WithStorageProvider.StorageDescriptor descriptor) { + myinit(descriptor); + + if (!(dfsCredentials instanceof AmazonS3DFSCredentials)) { + throw new RuntimeException("programming error"); + } + int maxConnections = 2; + dfsCredentials = ((AmazonS3DFSCredentials) dfsCredentials).toBuilder() + .maxConnections(maxConnections) + .requestTimeout(1000) + .build(); + mystart(); + + String content = "content of document qdm;mwm;ewmfmwemf;we;mfw;emf;llllle"; + String path = "a/b/c.txt"; + DSDocument document = new DSDocument(new DocumentFQN(path), new DocumentContent(content.getBytes())); + simpleDatasafeService.storeDocument(userIDAuth, document); + + // create more `not closed requests` than pool can handle + IntStream.range(0, maxConnections + 1).forEach(it -> { + DSDocumentStream ds = simpleDatasafeService.readDocumentStream(userIDAuth, document.getDocumentFQN()); + try { + // This causes exceptions when using authenticated encryption + ds.getDocumentStream().close(); + } catch (Exception ex) { + // Ignoring exception, i'm badly behaved client... + } + }); + } + private void show(String message, List listFound) { log.debug("---------------------------------"); log.debug(message); diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml b/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml index 7df7cf43f..9521b06b5 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml +++ b/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml @@ -5,7 +5,7 @@ datasafe-simple-adapter de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/SpringPropertiesToDFSCredentialsUtil.java b/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/SpringPropertiesToDFSCredentialsUtil.java index e90cbd06b..a78a45313 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/SpringPropertiesToDFSCredentialsUtil.java +++ b/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/SpringPropertiesToDFSCredentialsUtil.java @@ -23,6 +23,8 @@ static public DFSCredentials dfsCredentials(SpringDFSCredentialProperties proper .url(props.getUrl()) .noHttps(props.isNohttps()) .threadPoolSize(props.getThreadpoolsize()) + .requestTimeout(props.getRequesttimeout()) + .maxConnections(props.getMaxconnections()) .build(); } if (properties.getFilesystem() != null) { diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/properties/SpringAmazonS3DFSCredentialsProperties.java b/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/properties/SpringAmazonS3DFSCredentialsProperties.java index 546026ee2..0013a1e4c 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/properties/SpringAmazonS3DFSCredentialsProperties.java +++ b/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/properties/SpringAmazonS3DFSCredentialsProperties.java @@ -28,7 +28,9 @@ public class SpringAmazonS3DFSCredentialsProperties { " region: (optional)\n" + " rootbucket: (optional)\n" + " nohttps: (optional, default false - use https to reach s3 endpoint)\n" + - " threadpoolsize: (optional, default 5, how many workers should send chunk requests)\n"; + " threadpoolsize: (optional, default 5, how many workers should send chunk requests)\n" + + " maxconnections: (optional, if unset default of amazon is taken)\n" + + " requesttimeout: (optional, if unset default of amazon is taken)\n"; private String url; private String accesskey; @@ -42,4 +44,6 @@ public class SpringAmazonS3DFSCredentialsProperties { private boolean nohttps = false; private int threadpoolsize = 5; + private int maxconnections = 0; + private int requesttimeout = 0; } diff --git a/datasafe-simple-adapter/pom.xml b/datasafe-simple-adapter/pom.xml index bf45459a6..9682e0b26 100644 --- a/datasafe-simple-adapter/pom.xml +++ b/datasafe-simple-adapter/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-simple-adapter/readme.md b/datasafe-simple-adapter/readme.md index 29dce8864..0e9a54c9f 100644 --- a/datasafe-simple-adapter/readme.md +++ b/datasafe-simple-adapter/readme.md @@ -48,7 +48,12 @@ datasafe: accesskey: * secretkey: * region: eu-central-1 - rootbucket: adorsys-docusafe + rootbucket: adorsys-docusafe + nohttps: (optional, default false - use https to reach s3 endpoint) + threadpoolsize: (optional, default 5, how many workers should send chunk requests) + maxconnections: (optional, if unset default of amazon is taken) + requesttimeout: (optional, if unset default of amazon is taken) + ``` or for a filesystem like that: ``` diff --git a/datasafe-storage/datasafe-storage-api/pom.xml b/datasafe-storage/datasafe-storage-api/pom.xml index 0c138b2fd..1b568e2c4 100644 --- a/datasafe-storage/datasafe-storage-api/pom.xml +++ b/datasafe-storage/datasafe-storage-api/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe-storage - 1.0.0 + 1.0.0.1 datasafe-storage-api diff --git a/datasafe-storage/datasafe-storage-impl-db/pom.xml b/datasafe-storage/datasafe-storage-impl-db/pom.xml index 54b7c11d7..081f7905d 100644 --- a/datasafe-storage/datasafe-storage-impl-db/pom.xml +++ b/datasafe-storage/datasafe-storage-impl-db/pom.xml @@ -5,7 +5,7 @@ datasafe-storage de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-storage/datasafe-storage-impl-fs/pom.xml b/datasafe-storage/datasafe-storage-impl-fs/pom.xml index 939e1bf98..f413c22dc 100644 --- a/datasafe-storage/datasafe-storage-impl-fs/pom.xml +++ b/datasafe-storage/datasafe-storage-impl-fs/pom.xml @@ -5,7 +5,7 @@ datasafe-storage de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-storage/datasafe-storage-impl-s3/pom.xml b/datasafe-storage/datasafe-storage-impl-s3/pom.xml index 450ef21d7..a98f143f7 100644 --- a/datasafe-storage/datasafe-storage-impl-s3/pom.xml +++ b/datasafe-storage/datasafe-storage-impl-s3/pom.xml @@ -5,7 +5,7 @@ datasafe-storage de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-storage/pom.xml b/datasafe-storage/pom.xml index ecf36c1e6..e2ab3eb48 100644 --- a/datasafe-storage/pom.xml +++ b/datasafe-storage/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-test-storages/pom.xml b/datasafe-test-storages/pom.xml index d69957308..78ee77225 100644 --- a/datasafe-test-storages/pom.xml +++ b/datasafe-test-storages/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/datasafe-types-api/pom.xml b/datasafe-types-api/pom.xml index 5af08bf0c..b932184af 100644 --- a/datasafe-types-api/pom.xml +++ b/datasafe-types-api/pom.xml @@ -5,7 +5,7 @@ de.adorsys datasafe - 1.0.0 + 1.0.0.1 datasafe-types-api @@ -14,6 +14,11 @@ lombok + + org.slf4j + slf4j-api + + org.junit.jupiter junit-jupiter-api @@ -24,11 +29,6 @@ assertj-core test - - org.slf4j - slf4j-api - test - org.slf4j slf4j-simple @@ -44,36 +44,6 @@ guava test - - org.slf4j - slf4j-api - ${slf4j-simple.version} - - - org.slf4j - slf4j-simple - ${slf4j-simple.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${jupiter.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.junit.jupiter - junit-jupiter-api - test - - - diff --git a/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/BaseTypePasswordString.java b/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/BaseTypePasswordString.java index 2ee8d108b..bbb0e3800 100644 --- a/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/BaseTypePasswordString.java +++ b/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/BaseTypePasswordString.java @@ -2,75 +2,72 @@ import de.adorsys.datasafe.types.api.utils.Obfuscate; import lombok.EqualsAndHashCode; -import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; -import lombok.ToString; +import lombok.Synchronized; import lombok.extern.slf4j.Slf4j; import java.util.Arrays; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; /** * Wrapper for password sensitive data. */ @Slf4j -@RequiredArgsConstructor -@EqualsAndHashCode(exclude = {"toBeCleared", "cleared"} ) -@ToString +@EqualsAndHashCode public class BaseTypePasswordString { - private char[] value; - private AtomicBoolean toBeCleared = new AtomicBoolean(true); - private AtomicBoolean cleared = new AtomicBoolean(false); + + private final char[] value; + private Supplier passwordSupplier; + private boolean cleared = false; /** * ATTENTION *

- * caller of method gives responsiblity of char[] - * to this class. char[] will be nullyfied - * asap (after successfull read/write/list) + * caller of method gives ownership of {@code value[]} + * to this class. Value will be nullyfied after successful read/write/list. * * @param value will be nullified asap */ public BaseTypePasswordString(char[] value) { this.value = value; - toBeCleared.set(true); - cleared.set(false); + passwordSupplier = null; } /** - * caller of method makes sure, supplied char[] is deleted asap - * + * Argument provider is responsible for password cleanup * @param value will stay unchanged */ public BaseTypePasswordString(Supplier value) { - this.value = value.get(); - toBeCleared.set(false); - cleared.set(false); + this.passwordSupplier = value; + this.value = null; } - /** * clears the char array */ + @Synchronized public void clear() { - synchronized (value) { - if (toBeCleared.get()) { - cleared.set(true); - log.debug("CLEAR PASSWORD {}", this.getClass().getSimpleName()); - Arrays.fill(value, '0'); - } + if (null != value) { + Arrays.fill(value, '0'); } + cleared = true; } + /** + * Note that returned value is not immutable. + */ + @Synchronized @SneakyThrows public char[] getValue() { - synchronized (value) { - if (cleared.get()) { - throw new BaseTypePasswordStringException("Password was cleared before and must not be reused"); - } - return value; + if (null != passwordSupplier) { + return passwordSupplier.get(); + } + + if (cleared) { + throw new BaseTypePasswordStringException("Password was cleared before and must not be reused"); } + + return value; } @Override diff --git a/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadKeyPassword.java b/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadKeyPassword.java index 8425c4dbd..c88667aa4 100644 --- a/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadKeyPassword.java +++ b/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadKeyPassword.java @@ -4,11 +4,13 @@ /** * Wrapper for password for reading secret or private key entry. + * This class does not provide constructor with `raw` string as argument to reduce probability of user + * password to appear in memory dump (the less copies of it exists in memory - the better). */ public class ReadKeyPassword extends BaseTypePasswordString { /** - * caller of method makes sure, supplied char[] is deleted asap + * Caller of method makes sure, supplied char[] is deleted asap * @param readKeyPassword will stay unchanged */ public ReadKeyPassword(Supplier readKeyPassword) { @@ -16,12 +18,10 @@ public ReadKeyPassword(Supplier readKeyPassword) { } /** - * ATTENTION - * - * caller of method gives responsiblity of char[] - * to this class. char[] will be nullyfied - * asap (after successfull read/write/list) - * @param readKeyPassword will be nullified asap + * ATTENTION: + * caller of method gives ownership of {@code readKeyPassword} to this class. + * @code readKeyPassword} will be nullyfied after successful read/write/list. + * @param readKeyPassword Password to read key that will be cleared after read/write/list. */ public ReadKeyPassword(char[] readKeyPassword) { super(readKeyPassword); diff --git a/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadStorePassword.java b/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadStorePassword.java index 8dd1f0718..da650fc66 100644 --- a/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadStorePassword.java +++ b/datasafe-types-api/src/main/java/de/adorsys/datasafe/types/api/types/ReadStorePassword.java @@ -7,12 +7,16 @@ */ public class ReadStorePassword extends BaseTypePasswordString { + /** + * Consider using supplier-based constructor instead. + * This constructor exists because this kind of password has more relaxed security requirements compared + * to {@link ReadKeyPassword}, as it does not provide access to key content. + */ public ReadStorePassword(String readStorePassword) { - super(new Supplier() { - @Override - public char[] get() { - return readStorePassword.toCharArray(); - } - }); + super(readStorePassword::toCharArray); + } + + public ReadStorePassword(Supplier readStorePassword) { + super(readStorePassword); } } diff --git a/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/types/ReadKeyPasswordTest.java b/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/types/ReadKeyPasswordTest.java index 674e276b2..5f6f8edcf 100644 --- a/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/types/ReadKeyPasswordTest.java +++ b/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/types/ReadKeyPasswordTest.java @@ -5,15 +5,16 @@ import org.junit.jupiter.api.Test; import java.util.Arrays; -import java.util.function.Supplier; import static org.junit.jupiter.api.Assertions.assertThrows; -public class ReadKeyPasswordTest { - String passwordString = "a password that should be nullyfied"; +class ReadKeyPasswordTest { + + private static final String passwordString = "a password that should be nullyfied"; + @Test - public void testClearanceForUnsupplied() { + void testClearanceForUnsupplied() { char[] password = passwordString.toCharArray(); char[] copyOfPassword = Arrays.copyOf(password, password.length); @@ -21,41 +22,29 @@ public void testClearanceForUnsupplied() { Assertions.assertThat(Arrays.equals(password, copyOfPassword)).isTrue(); readKeyPassword.clear(); Assertions.assertThat(Arrays.equals(password, copyOfPassword)).isFalse(); - assertThrows(BaseTypePasswordStringException.class, () -> readKeyPassword.getValue()); + assertThrows(BaseTypePasswordStringException.class, readKeyPassword::getValue); } @Test - public void testClearanceForSupplied() { + void testClearanceForSupplied() { char[] password = passwordString.toCharArray(); char[] copyOfPassword = Arrays.copyOf(password, password.length); - ReadKeyPassword readKeyPassword = new ReadKeyPassword(new Supplier() { - @Override - public char[] get() { - return password; - } - }); + ReadKeyPassword readKeyPassword = new ReadKeyPassword(() -> password); Assertions.assertThat(Arrays.equals(password, copyOfPassword)).isTrue(); readKeyPassword.clear(); Assertions.assertThat(Arrays.equals(password, copyOfPassword)).isTrue(); Assertions.assertThat(Arrays.equals(readKeyPassword.getValue(), copyOfPassword)).isTrue(); - } @Test - public void testWithDeprecatedConstructor() { + void testWithDeprecatedConstructor() { String passwordString = "that is the password"; char[] copyOfPassword = Arrays.copyOf(passwordString.toCharArray(), passwordString.toCharArray().length); ReadKeyPassword readKeyPassword = ReadKeyPasswordTestFactory.getForString(passwordString); - ReadKeyPassword readKeyPasswordBackup = new ReadKeyPassword(new Supplier() { - @Override - public char[] get() { - return readKeyPassword.getValue(); - } - }); Assertions.assertThat(Arrays.equals(passwordString.toCharArray(), copyOfPassword)).isTrue(); readKeyPassword.clear(); Assertions.assertThat(Arrays.equals(passwordString.toCharArray(), copyOfPassword)).isTrue(); @@ -63,18 +52,17 @@ public char[] get() { } @Test - public void overwriteString() { + void overwriteString() { String s = "peter"; s.toCharArray()[0] = 'P'; Assertions.assertThat(s.equals("Peter")).isFalse(); } - @Test - public void useOnceOnly() { + void useOnceOnly() { ReadKeyPassword readKeyPassword = new ReadKeyPassword("peter".toCharArray()); readKeyPassword.clear(); - assertThrows(BaseTypePasswordStringException.class, () -> readKeyPassword.getValue()); + assertThrows(BaseTypePasswordStringException.class, readKeyPassword::getValue); } } diff --git a/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/utils/ReadKeyPasswordTestFactory.java b/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/utils/ReadKeyPasswordTestFactory.java index 7a80692f1..8942e4a12 100644 --- a/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/utils/ReadKeyPasswordTestFactory.java +++ b/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/utils/ReadKeyPasswordTestFactory.java @@ -2,15 +2,9 @@ import de.adorsys.datasafe.types.api.types.ReadKeyPassword; -import java.util.function.Supplier; - public class ReadKeyPasswordTestFactory { + public static ReadKeyPassword getForString(String a) { - return new ReadKeyPassword(new Supplier() { - @Override - public char[] get() { - return a.toCharArray(); - } - }); + return new ReadKeyPassword(a::toCharArray); } } diff --git a/last-module-codecoverage-check/pom.xml b/last-module-codecoverage-check/pom.xml index c0c9329dc..1e4dcd147 100644 --- a/last-module-codecoverage-check/pom.xml +++ b/last-module-codecoverage-check/pom.xml @@ -5,7 +5,7 @@ datasafe de.adorsys - 1.0.0 + 1.0.0.1 4.0.0 diff --git a/pom.xml b/pom.xml index 23eb9c427..e4fd2535b 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ de.adorsys datasafe - 1.0.0 + 1.0.0.1 datasafe Datasafe https://github.com/adorsys/datasafe