You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2019/03/08 13:14:46 UTC

[james-project] 03/05: JAMES-2669 Extract Swift as a specific object storage implementation

This is an automated email from the ASF dual-hosted git repository.

rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 44e376390b227684b45c27dc539dff010ab78d4e
Author: Antoine Duprat <ad...@linagora.com>
AuthorDate: Tue Feb 26 11:24:50 2019 +0100

    JAMES-2669 Extract Swift as a specific object storage implementation
---
 .../ObjectStorageBlobConfiguration.java            | 140 +++++-------------
 .../ObjectStorageDependenciesModule.java           |  18 +--
 .../objectstorage/SpecificAuthConfiguration.java   |  24 +++
 .../objectstorage/SwiftConfigurationReader.java    |  26 ----
 .../swift/SwiftAuthConfiguration.java              | 128 ++++++++++++++++
 .../objectstorage/swift/SwiftConfiguration.java    |  26 ++++
 .../SwiftKeystone2ConfigurationReader.java         |  40 ++---
 .../SwiftKeystone3ConfigurationReader.java         |  42 +++---
 .../objectstorage/swift/SwiftObjectStorage.java    |  66 +++++++++
 .../SwiftTmpAuthConfigurationReader.java           |  42 +++---
 .../objectstorage/MapConfigurationBuilder.java     |   2 +-
 .../ObjectStorageBlobConfigurationTest.java        |  89 ------------
 .../SwiftKeystone2ConfigurationReaderTest.java     |   1 +
 .../SwiftKeystone3ConfigurationReaderTest.java     |   1 +
 .../SwiftTmpAuthConfigurationReaderTest.java       |   1 +
 .../{guice => swift}/DockerSwiftTestRule.java      |  49 ++++---
 .../ObjectStorageBlobConfigurationTest.java        | 161 ++++++---------------
 .../ObjectStorageBlobStoreModuleTest.java          |  94 +++++++-----
 .../swift/SwiftObjectStorageTest.java              | 127 ++++++++++++++++
 .../james/CassandraRabbitMQJamesServerTest.java    |   2 +-
 .../james/modules/SwiftBlobStoreExtension.java     |   2 +-
 .../james/modules/TestSwiftBlobStoreModule.java    |   2 +-
 .../cassandra/cucumber/CucumberSwiftSingleton.java |   2 +-
 .../rabbitmq/cucumber/CucumberSwiftSingleton.java  |   2 +-
 .../jmap/rabbitmq/cucumber/RabbitMQStepdefs.java   |   2 +-
 25 files changed, 607 insertions(+), 482 deletions(-)

diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
index 01903e0..b36576f 100644
--- a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfiguration.java
@@ -27,9 +27,7 @@ import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.james.blob.objectstorage.ContainerName;
 import org.apache.james.blob.objectstorage.PayloadCodec;
-import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
-import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
-import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
+import org.apache.james.modules.objectstorage.swift.SwiftAuthConfiguration;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
@@ -37,10 +35,9 @@ import com.google.common.base.Strings;
 
 public class ObjectStorageBlobConfiguration {
 
-    private static final String OBJECTSTORAGE_CONFIGURATION_NAME = "blobstore";
+    public static final String OBJECTSTORAGE_CONFIGURATION_NAME = "blobstore";
     private static final String OBJECTSTORAGE_NAMESPACE = "objectstorage.namespace";
     private static final String OBJECTSTORAGE_PROVIDER = "objectstorage.provider";
-    private static final String OBJECTSTORAGE_SWIFT_AUTH_API = "objectstorage.swift.authapi";
     private static final String OBJECTSTORAGE_PAYLOAD_CODEC = "objectstorage.payload.codec";
     public static final String OBJECTSTORAGE_AES256_HEXSALT = "objectstorage.aes256.hexsalt";
     public static final String OBJECTSTORAGE_AES256_PASSWORD = "objectstorage.aes256.password";
@@ -48,7 +45,6 @@ public class ObjectStorageBlobConfiguration {
     public static ObjectStorageBlobConfiguration from(Configuration configuration) throws ConfigurationException {
         String provider = configuration.getString(OBJECTSTORAGE_PROVIDER, null);
         String namespace = configuration.getString(OBJECTSTORAGE_NAMESPACE, null);
-        String authApi = configuration.getString(OBJECTSTORAGE_SWIFT_AUTH_API, null);
         String codecName = configuration.getString(OBJECTSTORAGE_PAYLOAD_CODEC, null);
         Optional<String> aesSalt = Optional.ofNullable(configuration.getString(OBJECTSTORAGE_AES256_HEXSALT, null));
         Optional<char[]> aesPassword = Optional.ofNullable(configuration.getString(OBJECTSTORAGE_AES256_PASSWORD, null))
@@ -57,9 +53,6 @@ public class ObjectStorageBlobConfiguration {
         if (Strings.isNullOrEmpty(provider)) {
             throw new ConfigurationException("Mandatory configuration value " + OBJECTSTORAGE_PROVIDER + " is missing from " + OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
         }
-        if (Strings.isNullOrEmpty(authApi)) {
-            throw new ConfigurationException("Mandatory configuration value " + OBJECTSTORAGE_SWIFT_AUTH_API + " is missing from " + OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
-        }
         if (Strings.isNullOrEmpty(namespace)) {
             throw new ConfigurationException("Mandatory configuration value " + OBJECTSTORAGE_NAMESPACE + " is missing from " + OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
         }
@@ -72,101 +65,61 @@ public class ObjectStorageBlobConfiguration {
             .findAny()
             .orElseThrow(() -> new ConfigurationException("unknown payload codec : " + codecName));
 
-        Builder.RequireAuthConfiguration requireAuthConfiguration = builder()
+        return builder()
             .codec(payloadCodecFactory)
             .provider(ObjectStorageProvider.from(provider))
-            .container(ContainerName.of(namespace));
-
-        return defineAuthApi(configuration, authApi, requireAuthConfiguration)
+            .container(ContainerName.of(namespace))
+            .authConfiguration(SwiftAuthConfiguration.defineAuthApi(configuration))
             .aesSalt(aesSalt)
             .aesPassword(aesPassword)
             .build();
     }
 
-    private static Builder.ReadyToBuild defineAuthApi(Configuration configuration, String authApi, Builder.RequireAuthConfiguration requireAuthConfiguration) {
-        switch (authApi) {
-            case SwiftTempAuthObjectStorage.AUTH_API_NAME:
-                return requireAuthConfiguration.tempAuth(SwiftTmpAuthConfigurationReader.readSwiftConfiguration(configuration));
-            case SwiftKeystone2ObjectStorage.AUTH_API_NAME:
-                return requireAuthConfiguration.keystone2(SwiftKeystone2ConfigurationReader.readSwiftConfiguration(configuration));
-            case SwiftKeystone3ObjectStorage.AUTH_API_NAME:
-                return requireAuthConfiguration.keystone3(SwiftKeystone3ConfigurationReader.readSwiftConfiguration(configuration));
-        }
-        throw new IllegalStateException("unexpected auth api " + authApi);
-    }
-
 
     public static Builder.RequirePayloadCodec builder() {
-        return payloadCodec -> provider -> container -> new Builder.RequireAuthConfiguration(payloadCodec, provider, container);
+        return payloadCodec -> provider -> container -> authConfiguration -> new Builder.ReadyToBuild(payloadCodec, provider, container, authConfiguration);
     }
 
     public interface Builder {
         @FunctionalInterface
-        public interface RequirePayloadCodec {
+        interface RequirePayloadCodec {
             RequireProvider codec(PayloadCodecFactory codec);
         }
 
         @FunctionalInterface
-        public interface RequireProvider {
+        interface RequireProvider {
             RequireContainerName provider(ObjectStorageProvider provider);
         }
 
         @FunctionalInterface
-        public interface RequireContainerName {
+        interface RequireContainerName {
             RequireAuthConfiguration container(ContainerName container);
         }
 
-        public static class RequireAuthConfiguration {
-
-            private final PayloadCodecFactory payloadCodec;
-            private final ObjectStorageProvider provider;
-            private final ContainerName container;
-
-            private RequireAuthConfiguration(PayloadCodecFactory payloadCodec, ObjectStorageProvider provider, ContainerName container) {
-                this.payloadCodec = payloadCodec;
-                this.provider = provider;
-                this.container = container;
-            }
-
-            public ReadyToBuild tempAuth(SwiftTempAuthObjectStorage.Configuration authConfig) {
-                return new ReadyToBuild(payloadCodec, provider, container, SwiftTempAuthObjectStorage.AUTH_API_NAME, Optional.of(authConfig), Optional.empty(), Optional.empty());
-            }
-
-            public ReadyToBuild keystone2(SwiftKeystone2ObjectStorage.Configuration authConfig) {
-                return new ReadyToBuild(payloadCodec, provider, container, SwiftKeystone2ObjectStorage.AUTH_API_NAME, Optional.empty(), Optional.of(authConfig), Optional.empty());
-            }
-
-            public ReadyToBuild keystone3(SwiftKeystone3ObjectStorage.Configuration authConfig) {
-                return new ReadyToBuild(payloadCodec, provider, container, SwiftKeystone3ObjectStorage.AUTH_API_NAME, Optional.empty(), Optional.empty(), Optional.of(authConfig));
-            }
+        @FunctionalInterface
+        interface RequireAuthConfiguration {
+            ReadyToBuild authConfiguration(SpecificAuthConfiguration authConfiguration);
         }
 
-        public static class ReadyToBuild {
+        class ReadyToBuild {
 
             private final PayloadCodecFactory payloadCodecFactory;
             private final ObjectStorageProvider provider;
             private final ContainerName container;
-            private final String authApiName;
-            private final Optional<SwiftTempAuthObjectStorage.Configuration> tempAuth;
-            private final Optional<SwiftKeystone2ObjectStorage.Configuration> keystone2Configuration;
-            private final Optional<SwiftKeystone3ObjectStorage.Configuration> keystone3Configuration;
+            private final SpecificAuthConfiguration specificAuthConfiguration;
             private Optional<String> aesSalt;
             private Optional<char[]> aesPassword;
 
-            public ReadyToBuild(PayloadCodecFactory payloadCodecFactory, ObjectStorageProvider provider,
-                                ContainerName container, String authApiName,
-                                Optional<SwiftTempAuthObjectStorage.Configuration> tempAuth,
-                                Optional<SwiftKeystone2ObjectStorage.Configuration> keystone2Configuration,
-                                Optional<SwiftKeystone3ObjectStorage.Configuration> keystone3Configuration) {
+            public ReadyToBuild(PayloadCodecFactory payloadCodecFactory,
+                                ObjectStorageProvider provider,
+                                ContainerName container,
+                                SpecificAuthConfiguration specificAuthConfiguration) {
                 this.aesSalt = Optional.empty();
                 this.aesPassword = Optional.empty();
                 this.payloadCodecFactory = payloadCodecFactory;
                 this.provider = provider;
                 this.container = container;
-                this.authApiName = authApiName;
-                this.tempAuth = tempAuth;
-                this.keystone2Configuration = keystone2Configuration;
-                this.keystone3Configuration = keystone3Configuration;
+                this.specificAuthConfiguration = specificAuthConfiguration;
             }
 
             public ReadyToBuild aesSalt(String aesSalt) {
@@ -195,8 +148,7 @@ public class ObjectStorageBlobConfiguration {
                         .orElseThrow(() -> new IllegalStateException("AES code requires an non-empty password parameter"));
                 }
 
-                return new ObjectStorageBlobConfiguration(payloadCodecFactory, provider, container, aesSalt, aesPassword,
-                    authApiName, tempAuth, keystone2Configuration, keystone3Configuration);
+                return new ObjectStorageBlobConfiguration(payloadCodecFactory, provider, container, specificAuthConfiguration, aesSalt, aesPassword);
             }
 
         }
@@ -204,36 +156,24 @@ public class ObjectStorageBlobConfiguration {
     }
 
     private final PayloadCodecFactory payloadCodec;
-    private final String authApi;
     private final ContainerName namespace;
     private final ObjectStorageProvider provider;
-    private final Optional<SwiftTempAuthObjectStorage.Configuration> tempAuth;
-    private final Optional<SwiftKeystone2ObjectStorage.Configuration> keystone2Configuration;
-    private final Optional<SwiftKeystone3ObjectStorage.Configuration> keystone3Configuration;
+    private final SpecificAuthConfiguration specificAuthConfiguration;
     private Optional<String> aesSalt;
     private Optional<char[]> aesPassword;
 
     @VisibleForTesting
     ObjectStorageBlobConfiguration(PayloadCodecFactory payloadCodec, ObjectStorageProvider provider,
                                    ContainerName namespace,
+                                   SpecificAuthConfiguration specificAuthConfiguration,
                                    Optional<String> aesSalt,
-                                   Optional<char[]> aesPassword, String authApi,
-                                   Optional<SwiftTempAuthObjectStorage.Configuration> tempAuth,
-                                   Optional<SwiftKeystone2ObjectStorage.Configuration> keystone2Configuration,
-                                   Optional<SwiftKeystone3ObjectStorage.Configuration> keystone3Configuration) {
+                                   Optional<char[]> aesPassword) {
         this.payloadCodec = payloadCodec;
+        this.provider = provider;
+        this.namespace = namespace;
+        this.specificAuthConfiguration = specificAuthConfiguration;
         this.aesSalt = aesSalt;
         this.aesPassword = aesPassword;
-        this.authApi = authApi;
-        this.namespace = namespace;
-        this.provider = provider;
-        this.tempAuth = tempAuth;
-        this.keystone2Configuration = keystone2Configuration;
-        this.keystone3Configuration = keystone3Configuration;
-    }
-
-    public String getAuthApi() {
-        return authApi;
     }
 
     public ContainerName getNamespace() {
@@ -244,18 +184,6 @@ public class ObjectStorageBlobConfiguration {
         return provider;
     }
 
-    public Optional<SwiftTempAuthObjectStorage.Configuration> getTempAuthConfiguration() {
-        return tempAuth;
-    }
-
-    public Optional<SwiftKeystone2ObjectStorage.Configuration> getKeystone2Configuration() {
-        return keystone2Configuration;
-    }
-
-    public Optional<SwiftKeystone3ObjectStorage.Configuration> getKeystone3Configuration() {
-        return keystone3Configuration;
-    }
-
     public PayloadCodecFactory getPayloadCodecFactory() {
         return payloadCodec;
     }
@@ -264,6 +192,10 @@ public class ObjectStorageBlobConfiguration {
         return payloadCodec.create(this);
     }
 
+    public SpecificAuthConfiguration getSpecificAuthConfiguration() {
+        return specificAuthConfiguration;
+    }
+
     public Optional<String> getAesSalt() {
         return aesSalt;
     }
@@ -282,31 +214,25 @@ public class ObjectStorageBlobConfiguration {
         }
         ObjectStorageBlobConfiguration that = (ObjectStorageBlobConfiguration) o;
         return Objects.equals(payloadCodec, that.payloadCodec) &&
-            Objects.equals(authApi, that.authApi) &&
             Objects.equals(namespace, that.namespace) &&
             Objects.equals(provider, that.provider) &&
-            Objects.equals(tempAuth, that.tempAuth) &&
-            Objects.equals(keystone2Configuration, that.keystone2Configuration) &&
-            Objects.equals(keystone3Configuration, that.keystone3Configuration) &&
+            Objects.equals(specificAuthConfiguration, that.specificAuthConfiguration) &&
             Objects.equals(aesSalt, that.aesSalt) &&
             Objects.equals(aesPassword, that.aesPassword);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(payloadCodec, authApi, namespace, provider, tempAuth, keystone2Configuration, keystone3Configuration, aesSalt, aesPassword);
+        return Objects.hash(payloadCodec, namespace, provider, specificAuthConfiguration, aesSalt, aesPassword);
     }
 
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
             .add("payloadCodec", payloadCodec)
-            .add("authApi", authApi)
             .add("namespace", namespace)
             .add("provider", provider)
-            .add("tempAuth", tempAuth)
-            .add("keystone2Configuration", keystone2Configuration)
-            .add("keystone3Configuration", keystone3Configuration)
+            .add("specificAuthConfiguration", specificAuthConfiguration)
             .add("aesSalt", aesSalt)
             .add("aesPassword", aesPassword)
             .toString();
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
index 209ad4b..3d63afd 100644
--- a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/ObjectStorageDependenciesModule.java
@@ -32,10 +32,8 @@ import org.apache.james.blob.api.BlobId;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAO;
 import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
-import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
-import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
-import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
 import org.apache.james.modules.mailbox.ConfigurationComponent;
+import org.apache.james.modules.objectstorage.swift.SwiftObjectStorage;
 import org.apache.james.utils.PropertiesProvider;
 
 import com.google.inject.AbstractModule;
@@ -73,19 +71,7 @@ public class ObjectStorageDependenciesModule extends AbstractModule {
     }
 
     private ObjectStorageBlobsDAOBuilder.RequireContainerName selectDaoBuilder(ObjectStorageBlobConfiguration configuration) {
-        if (configuration.getProvider() != ObjectStorageProvider.SWIFT) {
-            throw new IllegalArgumentException("unknown provider " + configuration.getProvider());
-        }
-        switch (configuration.getAuthApi()) {
-            case SwiftTempAuthObjectStorage.AUTH_API_NAME:
-                return ObjectStorageBlobsDAO.builder(configuration.getTempAuthConfiguration().get());
-            case SwiftKeystone2ObjectStorage.AUTH_API_NAME:
-                return ObjectStorageBlobsDAO.builder(configuration.getKeystone2Configuration().get());
-            case SwiftKeystone3ObjectStorage.AUTH_API_NAME:
-                return ObjectStorageBlobsDAO.builder(configuration.getKeystone3Configuration().get());
-            default:
-                throw new IllegalArgumentException("unknown auth api " + configuration.getAuthApi());
-        }
+        return SwiftObjectStorage.builder(configuration);
     }
 
 }
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SpecificAuthConfiguration.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SpecificAuthConfiguration.java
new file mode 100644
index 0000000..0049288
--- /dev/null
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SpecificAuthConfiguration.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage;
+
+
+public interface SpecificAuthConfiguration {
+}
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftConfigurationReader.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftConfigurationReader.java
deleted file mode 100644
index 662a894..0000000
--- a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftConfigurationReader.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.modules.objectstorage;
-
-public interface SwiftConfigurationReader {
-    String OBJECTSTORAGE_SWIFT_ENDPOINT = "objectstorage.swift.endpoint";
-    String OBJECTSTORAGE_SWIFT_CREDENTIALS = "objectstorage.swift.credentials";
-    String OBJECTSTORAGE_SWIFT_REGION = "objectstorage.swift.region";
-}
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftAuthConfiguration.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftAuthConfiguration.java
new file mode 100644
index 0000000..9ded9a5
--- /dev/null
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftAuthConfiguration.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
+
+import java.util.Optional;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
+import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
+import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobConfiguration;
+import org.apache.james.modules.objectstorage.SpecificAuthConfiguration;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+
+public class SwiftAuthConfiguration implements SpecificAuthConfiguration {
+
+    private static final String OBJECTSTORAGE_SWIFT_AUTH_API = "objectstorage.swift.authapi";
+
+    public static SwiftAuthConfiguration defineAuthApi(Configuration configuration) throws ConfigurationException {
+        String authApi = configuration.getString(OBJECTSTORAGE_SWIFT_AUTH_API, null);
+        if (Strings.isNullOrEmpty(authApi)) {
+            throw new ConfigurationException("Mandatory configuration value " + OBJECTSTORAGE_SWIFT_AUTH_API + " is missing from " + ObjectStorageBlobConfiguration.OBJECTSTORAGE_CONFIGURATION_NAME + " configuration");
+        }
+
+        switch (authApi) {
+            case SwiftTempAuthObjectStorage.AUTH_API_NAME:
+                return tempAuth(SwiftTmpAuthConfigurationReader.readSwiftConfiguration(configuration));
+            case SwiftKeystone2ObjectStorage.AUTH_API_NAME:
+                return keystone2(SwiftKeystone2ConfigurationReader.readSwiftConfiguration(configuration));
+            case SwiftKeystone3ObjectStorage.AUTH_API_NAME:
+                return keystone3(SwiftKeystone3ConfigurationReader.readSwiftConfiguration(configuration));
+        }
+        throw new IllegalStateException("unexpected auth api " + authApi);
+    }
+
+    private static SwiftAuthConfiguration tempAuth(SwiftTempAuthObjectStorage.Configuration authConfig) {
+        return new SwiftAuthConfiguration(SwiftTempAuthObjectStorage.AUTH_API_NAME, Optional.of(authConfig), Optional.empty(), Optional.empty());
+    }
+
+    private static SwiftAuthConfiguration keystone2(SwiftKeystone2ObjectStorage.Configuration authConfig) {
+        return new SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME, Optional.empty(), Optional.of(authConfig), Optional.empty());
+    }
+
+    private static SwiftAuthConfiguration keystone3(SwiftKeystone3ObjectStorage.Configuration authConfig) {
+        return new SwiftAuthConfiguration(SwiftKeystone3ObjectStorage.AUTH_API_NAME, Optional.empty(), Optional.empty(), Optional.of(authConfig));
+    }
+
+    private final String authApiName;
+    private final Optional<SwiftTempAuthObjectStorage.Configuration> tempAuth;
+    private final Optional<SwiftKeystone2ObjectStorage.Configuration> keystone2Configuration;
+    private final Optional<SwiftKeystone3ObjectStorage.Configuration> keystone3Configuration;
+
+    @VisibleForTesting
+    SwiftAuthConfiguration(String authApiName,
+                           Optional<SwiftTempAuthObjectStorage.Configuration> tempAuth,
+                           Optional<SwiftKeystone2ObjectStorage.Configuration> keystone2Configuration,
+                           Optional<SwiftKeystone3ObjectStorage.Configuration> keystone3Configuration) {
+        this.authApiName = authApiName;
+        this.tempAuth = tempAuth;
+        this.keystone2Configuration = keystone2Configuration;
+        this.keystone3Configuration = keystone3Configuration;
+    }
+
+    public String getAuthApiName() {
+        return authApiName;
+    }
+
+    public Optional<SwiftTempAuthObjectStorage.Configuration> getTempAuth() {
+        return tempAuth;
+    }
+
+    public Optional<SwiftKeystone2ObjectStorage.Configuration> getKeystone2Configuration() {
+        return keystone2Configuration;
+    }
+
+    public Optional<SwiftKeystone3ObjectStorage.Configuration> getKeystone3Configuration() {
+        return keystone3Configuration;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof SwiftAuthConfiguration) {
+            SwiftAuthConfiguration that = (SwiftAuthConfiguration) o;
+            return Objects.equal(authApiName, that.authApiName) &&
+                Objects.equal(tempAuth, that.tempAuth) &&
+                Objects.equal(keystone2Configuration, that.keystone2Configuration) &&
+                Objects.equal(keystone3Configuration, that.keystone3Configuration);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hashCode(authApiName, tempAuth, keystone2Configuration, keystone3Configuration);
+    }
+
+    @Override
+    public final String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("authApiName", authApiName)
+            .add("tempAuth", tempAuth)
+            .add("keystone2Configuration", keystone2Configuration)
+            .add("keystone3Configuration", keystone3Configuration)
+            .toString();
+    }
+}
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftConfiguration.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftConfiguration.java
new file mode 100644
index 0000000..ab9a10f
--- /dev/null
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftConfiguration.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
+
+public interface SwiftConfiguration {
+    String OBJECTSTORAGE_SWIFT_ENDPOINT = "objectstorage.swift.endpoint";
+    String OBJECTSTORAGE_SWIFT_CREDENTIALS = "objectstorage.swift.credentials";
+    String OBJECTSTORAGE_SWIFT_REGION = "objectstorage.swift.region";
+}
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReader.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftKeystone2ConfigurationReader.java
similarity index 67%
rename from server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReader.java
rename to server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftKeystone2ConfigurationReader.java
index 26f951f..d69555f 100644
--- a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReader.java
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftKeystone2ConfigurationReader.java
@@ -1,23 +1,23 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
-package org.apache.james.modules.objectstorage;
+package org.apache.james.modules.objectstorage.swift;
 
 import java.net.URI;
 import java.util.Optional;
@@ -32,7 +32,7 @@ import org.apache.james.blob.objectstorage.swift.UserName;
 
 import com.google.common.base.Preconditions;
 
-public class SwiftKeystone2ConfigurationReader implements SwiftConfigurationReader {
+public class SwiftKeystone2ConfigurationReader implements SwiftConfiguration {
 
     static final String OBJECTSTORAGE_SWIFT_KEYSTONE_2_USERNAME =
         "objectstorage.swift.keystone2.username";
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReader.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftKeystone3ConfigurationReader.java
similarity index 79%
rename from server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReader.java
rename to server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftKeystone3ConfigurationReader.java
index 5263e19..46348d3 100644
--- a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReader.java
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftKeystone3ConfigurationReader.java
@@ -1,23 +1,23 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.modules.objectstorage;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
 
 import java.net.URI;
 import java.util.Optional;
@@ -41,7 +41,7 @@ import com.google.common.base.Preconditions;
  *
  * @link https://developer.openstack.org/api-ref/identity/v3/#authentication-and-token-management
  */
-public class SwiftKeystone3ConfigurationReader implements SwiftConfigurationReader {
+public class SwiftKeystone3ConfigurationReader implements SwiftConfiguration {
 
     static final String OBJECTSTORAGE_SWIFT_KEYSTONE_3_USER_NAME =
         "objectstorage.swift.keystone3.user.name";
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorage.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorage.java
new file mode 100644
index 0000000..bf5c9da
--- /dev/null
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorage.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
+
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAO;
+import org.apache.james.blob.objectstorage.ObjectStorageBlobsDAOBuilder;
+import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
+import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
+import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobConfiguration;
+import org.apache.james.modules.objectstorage.ObjectStorageProvider;
+
+public class SwiftObjectStorage {
+
+    public static ObjectStorageBlobsDAOBuilder.RequireContainerName builder(ObjectStorageBlobConfiguration configuration) {
+        if (configuration.getProvider() != ObjectStorageProvider.SWIFT) {
+            throw new IllegalArgumentException("unknown provider " + configuration.getProvider());
+        }
+        SwiftAuthConfiguration authConfiguration = (SwiftAuthConfiguration) configuration.getSpecificAuthConfiguration();
+        switch (authConfiguration.getAuthApiName()) {
+            case SwiftTempAuthObjectStorage.AUTH_API_NAME:
+                return authConfiguration.getTempAuth()
+                                    .map(ObjectStorageBlobsDAO::builder)
+                                    .orElseThrow(() -> new IllegalArgumentException("No TempAuth configuration found for tmpauth API"));
+            case SwiftKeystone2ObjectStorage.AUTH_API_NAME:
+                return authConfiguration.getKeystone2Configuration()
+                                    .map(ObjectStorageBlobsDAO::builder)
+                                    .orElseThrow(() -> new IllegalArgumentException("No Keystone2 configuration found for keystone2 API"));
+            case SwiftKeystone3ObjectStorage.AUTH_API_NAME:
+                return authConfiguration.getKeystone3Configuration()
+                                    .map(ObjectStorageBlobsDAO::builder)
+                                    .orElseThrow(() -> new IllegalArgumentException("No Keystone3 configuration found for keystone3 API"));
+            default:
+                throw new IllegalArgumentException("unknown auth api " + authConfiguration.getAuthApiName());
+        }
+    }
+
+    public static ObjectStorageBlobsDAOBuilder.RequireContainerName builder(SwiftTempAuthObjectStorage.Configuration testConfig) {
+        return SwiftTempAuthObjectStorage.daoBuilder(testConfig);
+    }
+
+    public static ObjectStorageBlobsDAOBuilder.RequireContainerName builder(SwiftKeystone2ObjectStorage.Configuration testConfig) {
+        return SwiftKeystone2ObjectStorage.daoBuilder(testConfig);
+    }
+
+    public static ObjectStorageBlobsDAOBuilder.RequireContainerName builder(SwiftKeystone3ObjectStorage.Configuration testConfig) {
+        return SwiftKeystone3ObjectStorage.daoBuilder(testConfig);
+    }
+}
diff --git a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReader.java b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftTmpAuthConfigurationReader.java
similarity index 71%
rename from server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReader.java
rename to server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftTmpAuthConfigurationReader.java
index 1066849..522da64 100644
--- a/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReader.java
+++ b/server/container/guice/blob-objectstorage-guice/src/main/java/org/apache/james/modules/objectstorage/swift/SwiftTmpAuthConfigurationReader.java
@@ -1,23 +1,23 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
-package org.apache.james.modules.objectstorage;
+package org.apache.james.modules.objectstorage.swift;
 
 import java.net.URI;
 import java.util.Optional;
@@ -34,7 +34,7 @@ import org.apache.james.blob.objectstorage.swift.UserName;
 
 import com.google.common.base.Preconditions;
 
-public class SwiftTmpAuthConfigurationReader implements SwiftConfigurationReader {
+public class SwiftTmpAuthConfigurationReader implements SwiftConfiguration {
 
     static final String OBJECTSTORAGE_SWIFT_TEMPAUTH_USERNAME =
         "objectstorage.swift.tempauth.username";
@@ -67,7 +67,7 @@ public class SwiftTmpAuthConfigurationReader implements SwiftConfigurationReader
         Identity identity = Identity.of(tenantName, userName);
 
         Optional<Region> region = Optional.ofNullable(
-                configuration.getString(SwiftConfigurationReader.OBJECTSTORAGE_SWIFT_REGION, null))
+                configuration.getString(SwiftConfiguration.OBJECTSTORAGE_SWIFT_REGION, null))
             .map(Region::of);
 
         Optional<PassHeaderName> passHeaderName = Optional.ofNullable(
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/MapConfigurationBuilder.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/MapConfigurationBuilder.java
index 1753b54..48168d0 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/MapConfigurationBuilder.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/MapConfigurationBuilder.java
@@ -23,7 +23,7 @@ import org.apache.commons.configuration.MapConfiguration;
 
 import com.google.common.collect.ImmutableMap;
 
-class MapConfigurationBuilder {
+public class MapConfigurationBuilder {
     private ImmutableMap.Builder<String, Object> config;
 
     public MapConfigurationBuilder() {
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
index 8dabe90..004b7bf 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
@@ -157,93 +157,4 @@ class ObjectStorageBlobConfigurationTest {
         assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(configuration)).isInstanceOf(IllegalStateException.class);
     }
 
-    @Test
-    void tempAuthPropertiesProvider() throws ConfigurationException {
-        ObjectStorageBlobConfiguration configuration = ObjectStorageBlobConfiguration.from(
-            new MapConfigurationBuilder()
-                .put("objectstorage.payload.codec", PayloadCodecFactory.DEFAULT.name())
-                .put("objectstorage.provider", "swift")
-                .put("objectstorage.namespace", "foo")
-                .put("objectstorage.swift.authapi", "tmpauth")
-                .put("objectstorage.swift.endpoint", "http://swift/endpoint")
-                .put("objectstorage.swift.credentials", "testing")
-                .put("objectstorage.swift.tempauth.username", "tester")
-                .put("objectstorage.swift.tempauth.tenantname", "test")
-                .put("objectstorage.swift.tempauth.passheadername", "X-Storage-Pass")
-                .put("objectstorage.swift.tempauth.userheadername", "X-Storage-User")
-                .build());
-        assertThat(configuration)
-            .isEqualTo(
-                ObjectStorageBlobConfiguration.builder()
-                    .codec(PayloadCodecFactory.DEFAULT)
-                    .provider(ObjectStorageProvider.SWIFT)
-                    .container(ContainerName.of("foo"))
-                    .tempAuth(SwiftTempAuthObjectStorage.configBuilder()
-                            .endpoint(URI.create("http://swift/endpoint"))
-                            .credentials(Credentials.of("testing"))
-                            .userName(UserName.of("tester"))
-                            .tenantName(TenantName.of("test"))
-                            .tempAuthHeaderUserName(UserHeaderName.of("X-Storage-User"))
-                            .tempAuthHeaderPassName(PassHeaderName.of("X-Storage-Pass"))
-                            .build())
-                    .build());
-    }
-
-    @Test
-    void keystone2PropertiesProvider() throws ConfigurationException {
-        ObjectStorageBlobConfiguration configuration = ObjectStorageBlobConfiguration.from(
-            new MapConfigurationBuilder()
-                .put("objectstorage.payload.codec", PayloadCodecFactory.DEFAULT.name())
-                .put("objectstorage.provider", "swift")
-                .put("objectstorage.namespace", "foo")
-                .put("objectstorage.swift.authapi", "keystone2")
-                .put("objectstorage.swift.endpoint", "http://swift/endpoint")
-                .put("objectstorage.swift.credentials", "creds")
-                .put("objectstorage.swift.keystone2.username", "demo")
-                .put("objectstorage.swift.keystone2.tenantname", "test")
-                .build());
-        assertThat(configuration)
-            .isEqualTo(
-                ObjectStorageBlobConfiguration.builder()
-                    .codec(PayloadCodecFactory.DEFAULT)
-                    .provider(ObjectStorageProvider.SWIFT)
-                    .container(ContainerName.of("foo"))
-                    .keystone2(SwiftKeystone2ObjectStorage.configBuilder()
-                        .endpoint(URI.create("http://swift/endpoint"))
-                        .credentials(Credentials.of("creds"))
-                        .userName(UserName.of("demo"))
-                        .tenantName(TenantName.of("test"))
-                        .build())
-                    .build());
-    }
-
-    @Test
-    void keystone3PropertiesProvider() throws ConfigurationException {
-        ObjectStorageBlobConfiguration configuration = ObjectStorageBlobConfiguration.from(
-            new MapConfigurationBuilder()
-                .put("objectstorage.payload.codec", PayloadCodecFactory.DEFAULT.name())
-                .put("objectstorage.provider", "swift")
-                .put("objectstorage.namespace", "foo")
-                .put("objectstorage.swift.authapi", "keystone3")
-                .put("objectstorage.swift.endpoint", "http://swift/endpoint")
-                .put("objectstorage.swift.credentials", "creds")
-                .put("objectstorage.swift.keystone3.user.name", "demo")
-                .put("objectstorage.swift.keystone3.user.domain", "Default")
-                .put("objectstorage.swift.keystone3.scope.project.name", "test")
-                .build());
-        assertThat(configuration)
-            .isEqualTo(
-                ObjectStorageBlobConfiguration.builder()
-                    .codec(PayloadCodecFactory.DEFAULT)
-                    .provider(ObjectStorageProvider.SWIFT)
-                    .container(ContainerName.of("foo"))
-                    .keystone3(SwiftKeystone3ObjectStorage.configBuilder()
-                        .endpoint(URI.create("http://swift/endpoint"))
-                        .credentials(Credentials.of("creds"))
-                        .project(Project.of(ProjectName.of("test")))
-                        .identity(IdentityV3.of(DomainName.of("Default"), UserName.of("demo")))
-                        .build())
-                    .build());
-    }
-
 }
\ No newline at end of file
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReaderTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReaderTest.java
index 83ed3c9..0fbf3c1 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReaderTest.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone2ConfigurationReaderTest.java
@@ -33,6 +33,7 @@ import org.apache.james.blob.objectstorage.swift.Region;
 import org.apache.james.blob.objectstorage.swift.SwiftKeystone2ObjectStorage;
 import org.apache.james.blob.objectstorage.swift.TenantName;
 import org.apache.james.blob.objectstorage.swift.UserName;
+import org.apache.james.modules.objectstorage.swift.SwiftKeystone2ConfigurationReader;
 import org.junit.jupiter.api.Test;
 
 class SwiftKeystone2ConfigurationReaderTest {
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReaderTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReaderTest.java
index 0d1dbf0..b590ef8 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReaderTest.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftKeystone3ConfigurationReaderTest.java
@@ -37,6 +37,7 @@ import org.apache.james.blob.objectstorage.swift.ProjectName;
 import org.apache.james.blob.objectstorage.swift.Region;
 import org.apache.james.blob.objectstorage.swift.SwiftKeystone3ObjectStorage;
 import org.apache.james.blob.objectstorage.swift.UserName;
+import org.apache.james.modules.objectstorage.swift.SwiftKeystone3ConfigurationReader;
 import org.junit.jupiter.api.Test;
 
 class SwiftKeystone3ConfigurationReaderTest {
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReaderTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReaderTest.java
index 5eeb96e..c719a01 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReaderTest.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/SwiftTmpAuthConfigurationReaderTest.java
@@ -35,6 +35,7 @@ import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
 import org.apache.james.blob.objectstorage.swift.TenantName;
 import org.apache.james.blob.objectstorage.swift.UserHeaderName;
 import org.apache.james.blob.objectstorage.swift.UserName;
+import org.apache.james.modules.objectstorage.swift.SwiftTmpAuthConfigurationReader;
 import org.junit.jupiter.api.Test;
 
 class SwiftTmpAuthConfigurationReaderTest {
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/guice/DockerSwiftTestRule.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
similarity index 75%
rename from server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/guice/DockerSwiftTestRule.java
rename to server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
index f3ad780..76481c3 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/guice/DockerSwiftTestRule.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/DockerSwiftTestRule.java
@@ -1,24 +1,25 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.modules.objectstorage.guice;
-
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
+
+import java.util.Optional;
 import java.util.UUID;
 
 import javax.inject.Inject;
@@ -35,6 +36,7 @@ import org.apache.james.blob.objectstorage.swift.UserName;
 import org.apache.james.modules.objectstorage.ObjectStorageBlobConfiguration;
 import org.apache.james.modules.objectstorage.ObjectStorageProvider;
 import org.apache.james.modules.objectstorage.PayloadCodecFactory;
+import org.apache.james.modules.objectstorage.swift.SwiftAuthConfiguration;
 import org.apache.james.utils.GuiceProbe;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
@@ -110,7 +112,10 @@ public class DockerSwiftTestRule implements GuiceModuleTestRule {
             .codec(payloadCodecFactory)
             .provider(ObjectStorageProvider.SWIFT)
             .container(containerName)
-            .keystone2(authConfiguration)
+            .authConfiguration(new SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME,
+                Optional.empty(),
+                Optional.of(authConfiguration),
+                Optional.empty()))
             .aesSalt("c603a7327ee3dcbc031d8d34b1096c605feca5e1")
             .aesPassword("dockerSwiftEncryption".toCharArray())
             .build();
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
similarity index 54%
copy from server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
copy to server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
index 8dabe90..631ae4c 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobConfigurationTest.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobConfigurationTest.java
@@ -1,10 +1,30 @@
-package org.apache.james.modules.objectstorage;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.net.URI;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.apache.commons.configuration.ConfigurationException;
@@ -22,6 +42,10 @@ import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
 import org.apache.james.blob.objectstorage.swift.TenantName;
 import org.apache.james.blob.objectstorage.swift.UserHeaderName;
 import org.apache.james.blob.objectstorage.swift.UserName;
+import org.apache.james.modules.objectstorage.MapConfigurationBuilder;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobConfiguration;
+import org.apache.james.modules.objectstorage.ObjectStorageProvider;
+import org.apache.james.modules.objectstorage.PayloadCodecFactory;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -59,104 +83,6 @@ class ObjectStorageBlobConfigurationTest {
         }
     }
 
-    @ParameterizedTest
-    @ArgumentsSource(RequiredParameters.class)
-    void shouldThrowWhenRequiredParameterOmitted(String toOmit) {
-        Map<String, Object> configurationWithFilteredKey = Maps.filterKeys(VALID_CONFIGURATION, key -> !toOmit.equals(key));
-
-        assertThat(configurationWithFilteredKey).doesNotContainKeys(toOmit);
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(new MapConfiguration(configurationWithFilteredKey)))
-            .isInstanceOf(ConfigurationException.class);
-    }
-
-    @ParameterizedTest
-    @ArgumentsSource(RequiredParameters.class)
-    void shouldThrowWhenRequiredParameterEmpty(String toEmpty) {
-        Map<String, Object> configurationWithFilteredKey = Maps.transformEntries(VALID_CONFIGURATION, (key, value) -> {
-            if (toEmpty.equals(key)) {
-                return "";
-            } else {
-                return value;
-            }
-        });
-
-        assertThat(configurationWithFilteredKey).containsEntry(toEmpty, "");
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(new MapConfiguration(configurationWithFilteredKey)))
-            .isInstanceOf(ConfigurationException.class);
-    }
-
-    @Test
-    void shouldBuildAnAESPayloadCodecForAESConfig() throws Exception {
-        ObjectStorageBlobConfiguration actual = ObjectStorageBlobConfiguration.from(new MapConfiguration(
-            ImmutableMap.<String, Object>builder()
-                .putAll(CONFIGURATION_WITHOUT_CODEC)
-                .put("objectstorage.payload.codec", PayloadCodecFactory.AES256.name())
-                .put("objectstorage.aes256.hexsalt", "12345123451234512345")
-                .put("objectstorage.aes256.password", "james is great")
-            .build()));
-        assertThat(actual.getPayloadCodecFactory()).isEqualTo(PayloadCodecFactory.AES256);
-        assertThat(actual.getAesSalt()).contains("12345123451234512345");
-        assertThat(actual.getAesPassword()).contains("james is great".toCharArray());
-    }
-
-    @Test
-    void shouldFailIfCodecKeyIsIncorrect() throws Exception {
-        MapConfiguration configuration = new MapConfiguration(
-            ImmutableMap.<String, Object>builder()
-                .putAll(CONFIGURATION_WITHOUT_CODEC)
-                .put("objectstorage.payload.codec", "aes255")
-                .build());
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(configuration)).isInstanceOf(ConfigurationException.class);
-    }
-
-    @Test
-    void shouldFailForAESCodecWhenSaltKeyIsMissing() throws Exception {
-        MapConfiguration configuration = new MapConfiguration(
-            ImmutableMap.<String, Object>builder()
-                .putAll(CONFIGURATION_WITHOUT_CODEC)
-                .put("objectstorage.payload.codec", PayloadCodecFactory.AES256.name())
-                .put("objectstorage.aes256.password", "james is great")
-                .build());
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(configuration)).isInstanceOf(IllegalStateException.class);
-    }
-
-    @Test
-    void shouldFailForAESCodecWhenSaltKeyIsEmpty() throws Exception {
-        MapConfiguration configuration = new MapConfiguration(
-            ImmutableMap.<String, Object>builder()
-                .putAll(CONFIGURATION_WITHOUT_CODEC)
-                .put("objectstorage.payload.codec", PayloadCodecFactory.AES256.name())
-                .put("objectstorage.aes256.hexsalt", "")
-                .put("objectstorage.aes256.password", "james is great")
-                .build());
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(configuration)).isInstanceOf(IllegalStateException.class);
-    }
-
-    @Test
-    void shouldFailForAESCodecWhenPasswordKeyIsMissing() throws Exception {
-        MapConfiguration configuration = new MapConfiguration(
-            ImmutableMap.<String, Object>builder()
-                .putAll(CONFIGURATION_WITHOUT_CODEC)
-                .put("objectstorage.payload.codec", PayloadCodecFactory.AES256.name())
-                .put("objectstorage.aes256.hexsalt", "12345123451234512345")
-                .build());
-
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(configuration)).isInstanceOf(IllegalStateException.class);
-    }
-
-    @Test
-    void shouldFailForAESCodecWhenPasswordKeyIsEmpty() throws Exception {
-        MapConfiguration configuration = new MapConfiguration(
-            ImmutableMap.<String, Object>builder()
-                .putAll(CONFIGURATION_WITHOUT_CODEC)
-                .put("objectstorage.payload.codec", PayloadCodecFactory.AES256.name())
-                .put("objectstorage.aes256.hexsalt", "12345123451234512345")
-                .put("objectstorage.aes256.password", "")
-                .build());
-
-        assertThatThrownBy(() -> ObjectStorageBlobConfiguration.from(configuration)).isInstanceOf(IllegalStateException.class);
-    }
-
     @Test
     void tempAuthPropertiesProvider() throws ConfigurationException {
         ObjectStorageBlobConfiguration configuration = ObjectStorageBlobConfiguration.from(
@@ -178,14 +104,17 @@ class ObjectStorageBlobConfigurationTest {
                     .codec(PayloadCodecFactory.DEFAULT)
                     .provider(ObjectStorageProvider.SWIFT)
                     .container(ContainerName.of("foo"))
-                    .tempAuth(SwiftTempAuthObjectStorage.configBuilder()
+                    .authConfiguration(new SwiftAuthConfiguration(SwiftTempAuthObjectStorage.AUTH_API_NAME,
+                        Optional.of(SwiftTempAuthObjectStorage.configBuilder()
                             .endpoint(URI.create("http://swift/endpoint"))
                             .credentials(Credentials.of("testing"))
                             .userName(UserName.of("tester"))
                             .tenantName(TenantName.of("test"))
                             .tempAuthHeaderUserName(UserHeaderName.of("X-Storage-User"))
                             .tempAuthHeaderPassName(PassHeaderName.of("X-Storage-Pass"))
-                            .build())
+                            .build()),
+                        Optional.empty(),
+                        Optional.empty()))
                     .build());
     }
 
@@ -208,12 +137,15 @@ class ObjectStorageBlobConfigurationTest {
                     .codec(PayloadCodecFactory.DEFAULT)
                     .provider(ObjectStorageProvider.SWIFT)
                     .container(ContainerName.of("foo"))
-                    .keystone2(SwiftKeystone2ObjectStorage.configBuilder()
-                        .endpoint(URI.create("http://swift/endpoint"))
-                        .credentials(Credentials.of("creds"))
-                        .userName(UserName.of("demo"))
-                        .tenantName(TenantName.of("test"))
-                        .build())
+                    .authConfiguration(new SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME,
+                        Optional.empty(),
+                        Optional.of(SwiftKeystone2ObjectStorage.configBuilder()
+                            .endpoint(URI.create("http://swift/endpoint"))
+                            .credentials(Credentials.of("creds"))
+                            .userName(UserName.of("demo"))
+                            .tenantName(TenantName.of("test"))
+                            .build()),
+                        Optional.empty()))
                     .build());
     }
 
@@ -237,12 +169,15 @@ class ObjectStorageBlobConfigurationTest {
                     .codec(PayloadCodecFactory.DEFAULT)
                     .provider(ObjectStorageProvider.SWIFT)
                     .container(ContainerName.of("foo"))
-                    .keystone3(SwiftKeystone3ObjectStorage.configBuilder()
-                        .endpoint(URI.create("http://swift/endpoint"))
-                        .credentials(Credentials.of("creds"))
-                        .project(Project.of(ProjectName.of("test")))
-                        .identity(IdentityV3.of(DomainName.of("Default"), UserName.of("demo")))
-                        .build())
+                    .authConfiguration(new SwiftAuthConfiguration(SwiftKeystone3ObjectStorage.AUTH_API_NAME,
+                        Optional.empty(),
+                        Optional.empty(),
+                        Optional.of(SwiftKeystone3ObjectStorage.configBuilder()
+                            .endpoint(URI.create("http://swift/endpoint"))
+                            .credentials(Credentials.of("creds"))
+                            .project(Project.of(ProjectName.of("test")))
+                            .identity(IdentityV3.of(DomainName.of("Default"), UserName.of("demo")))
+                            .build())))
                     .build());
     }
 
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobStoreModuleTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
similarity index 58%
rename from server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobStoreModuleTest.java
rename to server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
index 19b2d87..dcb30ff 100644
--- a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/ObjectStorageBlobStoreModuleTest.java
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/ObjectStorageBlobStoreModuleTest.java
@@ -1,26 +1,27 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.modules.objectstorage;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
 
 import static org.assertj.core.api.Assertions.assertThatCode;
 
+import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Stream;
 
@@ -42,6 +43,10 @@ import org.apache.james.blob.objectstorage.swift.SwiftTempAuthObjectStorage;
 import org.apache.james.blob.objectstorage.swift.TenantName;
 import org.apache.james.blob.objectstorage.swift.UserHeaderName;
 import org.apache.james.blob.objectstorage.swift.UserName;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobConfiguration;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobStoreModule;
+import org.apache.james.modules.objectstorage.ObjectStorageProvider;
+import org.apache.james.modules.objectstorage.PayloadCodecFactory;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.jupiter.api.extension.ExtensionContext;
@@ -75,36 +80,45 @@ class ObjectStorageBlobStoreModuleTest {
                 .codec(PayloadCodecFactory.DEFAULT)
                 .provider(ObjectStorageProvider.SWIFT)
                 .container(generateContainerName())
-                .tempAuth(SwiftTempAuthObjectStorage.configBuilder()
-                    .endpoint(dockerSwift.swiftEndpoint())
-                    .credentials(Credentials.of("testing"))
-                    .userName(UserName.of("tester"))
-                    .tenantName(TenantName.of("test"))
-                    .tempAuthHeaderUserName(UserHeaderName.of("X-Storage-User"))
-                    .tempAuthHeaderPassName(PassHeaderName.of("X-Storage-Pass"))
-                    .build())
+                .authConfiguration(new SwiftAuthConfiguration(SwiftTempAuthObjectStorage.AUTH_API_NAME,
+                    Optional.of(SwiftTempAuthObjectStorage.configBuilder()
+                        .endpoint(dockerSwift.swiftEndpoint())
+                        .credentials(Credentials.of("testing"))
+                        .userName(UserName.of("tester"))
+                        .tenantName(TenantName.of("test"))
+                        .tempAuthHeaderUserName(UserHeaderName.of("X-Storage-User"))
+                        .tempAuthHeaderPassName(PassHeaderName.of("X-Storage-Pass"))
+                        .build()),
+                    Optional.empty(),
+                    Optional.empty()))
                 .build();
             ObjectStorageBlobConfiguration keystone2 = ObjectStorageBlobConfiguration.builder()
                 .codec(PayloadCodecFactory.DEFAULT)
                 .provider(ObjectStorageProvider.SWIFT)
                 .container(generateContainerName())
-                .keystone2(SwiftKeystone2ObjectStorage.configBuilder()
-                    .endpoint(dockerSwift.keystoneV2Endpoint())
-                    .credentials(Credentials.of("demo"))
-                    .userName(UserName.of("demo"))
-                    .tenantName(TenantName.of("test"))
-                    .build())
+                .authConfiguration(new SwiftAuthConfiguration(SwiftKeystone2ObjectStorage.AUTH_API_NAME,
+                    Optional.empty(),
+                    Optional.of(SwiftKeystone2ObjectStorage.configBuilder()
+                        .endpoint(dockerSwift.keystoneV2Endpoint())
+                        .credentials(Credentials.of("demo"))
+                        .userName(UserName.of("demo"))
+                        .tenantName(TenantName.of("test"))
+                        .build()),
+                    Optional.empty()))
                 .build();
             ObjectStorageBlobConfiguration keystone3 = ObjectStorageBlobConfiguration.builder()
                 .codec(PayloadCodecFactory.DEFAULT)
                 .provider(ObjectStorageProvider.SWIFT)
                 .container(generateContainerName())
-                .keystone3(SwiftKeystone3ObjectStorage.configBuilder()
-                    .endpoint(dockerSwift.keystoneV3Endpoint())
-                    .credentials(Credentials.of("demo"))
-                    .project(Project.of(ProjectName.of("test")))
-                    .identity(IdentityV3.of(DomainName.of("Default"), UserName.of("demo")))
-                    .build())
+                .authConfiguration(new SwiftAuthConfiguration(SwiftKeystone3ObjectStorage.AUTH_API_NAME,
+                    Optional.empty(),
+                    Optional.empty(),
+                    Optional.of(SwiftKeystone3ObjectStorage.configBuilder()
+                        .endpoint(dockerSwift.keystoneV3Endpoint())
+                        .credentials(Credentials.of("demo"))
+                        .project(Project.of(ProjectName.of("test")))
+                        .identity(IdentityV3.of(DomainName.of("Default"), UserName.of("demo")))
+                        .build())))
                 .build();
             return Stream.of(tmpAuth, keystone2, keystone3).map(Arguments::of);
         }
diff --git a/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java
new file mode 100644
index 0000000..262019a
--- /dev/null
+++ b/server/container/guice/blob-objectstorage-guice/src/test/java/org/apache/james/modules/objectstorage/swift/SwiftObjectStorageTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.james.modules.objectstorage.swift;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.Optional;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.james.blob.objectstorage.ContainerName;
+import org.apache.james.modules.objectstorage.ObjectStorageBlobConfiguration;
+import org.apache.james.modules.objectstorage.ObjectStorageProvider;
+import org.apache.james.modules.objectstorage.PayloadCodecFactory;
+import org.junit.jupiter.api.Test;
+
+class SwiftObjectStorageTest {
+
+    @Test
+    void builderShouldThrowWhenTempAuthAPIAndNoConfiguration() throws Exception {
+        ObjectStorageBlobConfiguration objectStorageBlobConfiguration = ObjectStorageBlobConfiguration.builder()
+            .codec(PayloadCodecFactory.DEFAULT)
+            .provider(ObjectStorageProvider.SWIFT)
+            .container(ContainerName.of("myContainer"))
+            .authConfiguration(new SwiftAuthConfiguration("tmpauth", Optional.empty(), Optional.empty(), Optional.empty()))
+            .build();
+        assertThatThrownBy(() -> SwiftObjectStorage.builder(objectStorageBlobConfiguration))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("No TempAuth configuration found for tmpauth API");
+    }
+
+    @Test
+    void builderShouldWorkWhenTempAuthAPI() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstorage.swift.endpoint", "http://auth.example.com/v2.0");
+        configuration.addProperty("objectstorage.swift.credentials", "this_is_a_secret");
+        configuration.addProperty("objectstorage.swift.tempauth.username", "user");
+        configuration.addProperty("objectstorage.swift.tempauth.tenantname", "tenant");
+        configuration.addProperty("objectstorage.swift.authapi", "tmpauth");
+
+        ObjectStorageBlobConfiguration objectStorageBlobConfiguration = ObjectStorageBlobConfiguration.builder()
+            .codec(PayloadCodecFactory.DEFAULT)
+            .provider(ObjectStorageProvider.SWIFT)
+            .container(ContainerName.of("myContainer"))
+            .authConfiguration(SwiftAuthConfiguration.from(configuration))
+            .build();
+        SwiftObjectStorage.builder(objectStorageBlobConfiguration);
+    }
+
+    @Test
+    void builderShouldThrowWhenKeystone2APIAndNoConfiguration() throws Exception {
+        ObjectStorageBlobConfiguration objectStorageBlobConfiguration = ObjectStorageBlobConfiguration.builder()
+            .codec(PayloadCodecFactory.DEFAULT)
+            .provider(ObjectStorageProvider.SWIFT)
+            .container(ContainerName.of("myContainer"))
+            .authConfiguration(new SwiftAuthConfiguration("keystone2", Optional.empty(), Optional.empty(), Optional.empty()))
+            .build();
+        assertThatThrownBy(() -> SwiftObjectStorage.builder(objectStorageBlobConfiguration))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("No Keystone2 configuration found for keystone2 API");
+    }
+
+    @Test
+    void builderShouldWorkWhenKeystone2API() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstorage.swift.endpoint", "http://auth.example.com/v2.0");
+        configuration.addProperty("objectstorage.swift.credentials", "this_is_a_secret");
+        configuration.addProperty("objectstorage.swift.keystone2.username", "user");
+        configuration.addProperty("objectstorage.swift.keystone2.tenantname", "tenant");
+        configuration.addProperty("objectstorage.swift.authapi", "keystone2");
+
+        ObjectStorageBlobConfiguration objectStorageBlobConfiguration = ObjectStorageBlobConfiguration.builder()
+            .codec(PayloadCodecFactory.DEFAULT)
+            .provider(ObjectStorageProvider.SWIFT)
+            .container(ContainerName.of("myContainer"))
+            .authConfiguration(SwiftAuthConfiguration.from(configuration))
+            .build();
+        SwiftObjectStorage.builder(objectStorageBlobConfiguration);
+    }
+
+    @Test
+    void builderShouldThrowWhenKeystone3APIAndNoConfiguration() throws Exception {
+        ObjectStorageBlobConfiguration objectStorageBlobConfiguration = ObjectStorageBlobConfiguration.builder()
+            .codec(PayloadCodecFactory.DEFAULT)
+            .provider(ObjectStorageProvider.SWIFT)
+            .container(ContainerName.of("myContainer"))
+            .authConfiguration(new SwiftAuthConfiguration("keystone3", Optional.empty(), Optional.empty(), Optional.empty()))
+            .build();
+        assertThatThrownBy(() -> SwiftObjectStorage.builder(objectStorageBlobConfiguration))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessage("No Keystone3 configuration found for keystone3 API");
+    }
+
+    @Test
+    void builderShouldWorkWhenKeystone3API() throws Exception {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        configuration.addProperty("objectstorage.swift.endpoint", "http://auth.example.com/v2.0");
+        configuration.addProperty("objectstorage.swift.credentials", "this_is_a_secret");
+        configuration.addProperty("objectstorage.swift.keystone3.user.name", "user");
+        configuration.addProperty("objectstorage.swift.keystone3.user.domain", "domain");
+        configuration.addProperty("objectstorage.swift.authapi", "keystone3");
+
+        ObjectStorageBlobConfiguration objectStorageBlobConfiguration = ObjectStorageBlobConfiguration.builder()
+            .codec(PayloadCodecFactory.DEFAULT)
+            .provider(ObjectStorageProvider.SWIFT)
+            .container(ContainerName.of("myContainer"))
+            .authConfiguration(SwiftAuthConfiguration.from(configuration))
+            .build();
+        SwiftObjectStorage.builder(objectStorageBlobConfiguration);
+    }
+}
\ No newline at end of file
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerTest.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerTest.java
index 46bdb23..b5ddbed 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerTest.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/CassandraRabbitMQJamesServerTest.java
@@ -31,7 +31,7 @@ import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.SwiftBlobStoreExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.objectstorage.PayloadCodecFactory;
-import org.apache.james.modules.objectstorage.guice.DockerSwiftTestRule;
+import org.apache.james.modules.objectstorage.swift.DockerSwiftTestRule;
 import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.modules.protocols.SmtpGuiceProbe;
 import org.apache.james.utils.DataProbeImpl;
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/SwiftBlobStoreExtension.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/SwiftBlobStoreExtension.java
index d113f1d..2aee3f8 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/SwiftBlobStoreExtension.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/SwiftBlobStoreExtension.java
@@ -22,7 +22,7 @@ package org.apache.james.modules;
 import org.apache.james.GuiceModuleTestExtension;
 import org.apache.james.modules.blobstore.BlobStoreChoosingConfiguration;
 import org.apache.james.modules.objectstorage.PayloadCodecFactory;
-import org.apache.james.modules.objectstorage.guice.DockerSwiftTestRule;
+import org.apache.james.modules.objectstorage.swift.DockerSwiftTestRule;
 import org.junit.jupiter.api.extension.ExtensionContext;
 
 import com.google.inject.Module;
diff --git a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/TestSwiftBlobStoreModule.java b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/TestSwiftBlobStoreModule.java
index 2f4a052..4638109 100644
--- a/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/TestSwiftBlobStoreModule.java
+++ b/server/container/guice/cassandra-rabbitmq-guice/src/test/java/org/apache/james/modules/TestSwiftBlobStoreModule.java
@@ -20,7 +20,7 @@
 package org.apache.james.modules;
 
 import org.apache.james.modules.blobstore.BlobStoreChoosingConfiguration;
-import org.apache.james.modules.objectstorage.guice.DockerSwiftTestRule;
+import org.apache.james.modules.objectstorage.swift.DockerSwiftTestRule;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Module;
diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CucumberSwiftSingleton.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CucumberSwiftSingleton.java
index 09200cd..7af9ec8 100644
--- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CucumberSwiftSingleton.java
+++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/cucumber/CucumberSwiftSingleton.java
@@ -19,7 +19,7 @@
 package org.apache.james.jmap.cassandra.cucumber;
 
 import org.apache.james.modules.objectstorage.PayloadCodecFactory;
-import org.apache.james.modules.objectstorage.guice.DockerSwiftTestRule;
+import org.apache.james.modules.objectstorage.swift.DockerSwiftTestRule;
 
 public class CucumberSwiftSingleton {
 
diff --git a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/CucumberSwiftSingleton.java b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/CucumberSwiftSingleton.java
index 18b58ab..7695ca3 100644
--- a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/CucumberSwiftSingleton.java
+++ b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/CucumberSwiftSingleton.java
@@ -19,7 +19,7 @@
 package org.apache.james.jmap.rabbitmq.cucumber;
 
 import org.apache.james.modules.objectstorage.PayloadCodecFactory;
-import org.apache.james.modules.objectstorage.guice.DockerSwiftTestRule;
+import org.apache.james.modules.objectstorage.swift.DockerSwiftTestRule;
 
 public class CucumberSwiftSingleton {
 
diff --git a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/RabbitMQStepdefs.java b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/RabbitMQStepdefs.java
index 027f793..b97c96e 100644
--- a/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/RabbitMQStepdefs.java
+++ b/server/protocols/jmap-integration-testing/rabbitmq-jmap-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/cucumber/RabbitMQStepdefs.java
@@ -41,7 +41,7 @@ import org.apache.james.modules.TestElasticSearchModule;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.TestRabbitMQModule;
 import org.apache.james.modules.TestSwiftBlobStoreModule;
-import org.apache.james.modules.objectstorage.guice.DockerSwiftTestRule;
+import org.apache.james.modules.objectstorage.swift.DockerSwiftTestRule;
 import org.apache.james.server.CassandraTruncateTableTask;
 import org.apache.james.server.core.configuration.Configuration;
 import org.junit.rules.TemporaryFolder;


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org