You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by jh...@apache.org on 2023/01/26 22:22:48 UTC

[james-project] 02/03: [JAMES-3687] adds support for authentication scheme in the configuration

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

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

commit a2ca77601da3eae981ecf7d57e4942da59ecc620
Author: Jean Helou <jh...@codamens.fr>
AuthorDate: Thu Nov 24 23:28:00 2022 +0100

    [JAMES-3687] adds support for authentication scheme in the configuration
---
 .../backends/pulsar/PulsarConfiguration.scala      |  59 ++++++++++--
 .../backends/pulsar/DockerPulsarExtension.java     |   4 +-
 .../backends/pulsar/PulsarConfigurationTest.java   | 103 ++++++++++++++++++++-
 3 files changed, 157 insertions(+), 9 deletions(-)

diff --git a/backends-common/pulsar/src/main/scala/org/apache/james/backends/pulsar/PulsarConfiguration.scala b/backends-common/pulsar/src/main/scala/org/apache/james/backends/pulsar/PulsarConfiguration.scala
index b3cbda2bd8..7e790f29c6 100644
--- a/backends-common/pulsar/src/main/scala/org/apache/james/backends/pulsar/PulsarConfiguration.scala
+++ b/backends-common/pulsar/src/main/scala/org/apache/james/backends/pulsar/PulsarConfiguration.scala
@@ -1,4 +1,4 @@
-/****************************************************************
+/** **************************************************************
  * 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        *
@@ -6,16 +6,16 @@
  * 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                 *
- *                                                              *
+ * *
+ * 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.backends.pulsar
 
@@ -27,16 +27,45 @@ object PulsarConfiguration {
   val BROKER_URI_PROPERTY_NAME = "broker.uri"
   val ADMIN_URI_PROPERTY_NAME = "admin.uri"
   val NAMESPACE_PROPERTY_NAME = "namespace"
+  val AUTHENTICATION_TYPE_PROPERTY_NAME = "authentication.type"
+  val AUTHENTICATION_TYPE_NO_AUTH = "no-auth"
+  val AUTHENTICATION_TYPE_AUTH_TOKEN = "token"
+  val AUTHENTICATION_TYPE_AUTH_BASIC = "basic"
+  val AUTHENTICATION_TOKEN_PROPERTY_NAME = "authentication.token"
+  val AUTHENTICATION_BASIC_USERID_PROPERTY_NAME = "authentication.basic.userId"
+  val AUTHENTICATION_BASIC_PASSWORD_PROPERTY_NAME = "authentication.basic.password"
+
 
   def from(configuration: Configuration): PulsarConfiguration = {
     val brokerUri: String = extractUri(configuration, BROKER_URI_PROPERTY_NAME)
     val adminUri: String = extractUri(configuration, ADMIN_URI_PROPERTY_NAME)
+    val authTypeString: String = configuration.getString(AUTHENTICATION_TYPE_PROPERTY_NAME, AUTHENTICATION_TYPE_NO_AUTH);
+    val auth = authTypeString match {
+      case AUTHENTICATION_TYPE_NO_AUTH => Auth.NoAuth
+
+      case AUTHENTICATION_TYPE_AUTH_TOKEN =>
+        val token = configuration.getString(AUTHENTICATION_TOKEN_PROPERTY_NAME)
+        if (Strings.isNullOrEmpty(token))
+          throw new IllegalStateException(s"You need to specify a non-empty value for ${AUTHENTICATION_TOKEN_PROPERTY_NAME}")
+        Auth.Token(token)
+
+      case AUTHENTICATION_TYPE_AUTH_BASIC =>
+        val userId = configuration.getString(AUTHENTICATION_BASIC_USERID_PROPERTY_NAME)
+        if (Strings.isNullOrEmpty(userId))
+          throw new IllegalStateException(s"You need to specify a non-empty value for ${AUTHENTICATION_BASIC_USERID_PROPERTY_NAME}")
+        val password = configuration.getString(AUTHENTICATION_BASIC_PASSWORD_PROPERTY_NAME)
+        if (Strings.isNullOrEmpty(password))
+          throw new IllegalStateException(s"You need to specify a non-empty value for ${AUTHENTICATION_BASIC_PASSWORD_PROPERTY_NAME}")
+        Auth.Basic(userId, password)
 
+      case _ =>
+        throw new NotImplementedError(s"Authentication type $authTypeString is not implemented")
+    }
 
     val namespace = configuration.getString(NAMESPACE_PROPERTY_NAME)
     if (Strings.isNullOrEmpty(namespace))
       throw new IllegalStateException(s"You need to specify the pulsar namespace as ${NAMESPACE_PROPERTY_NAME}")
-    new PulsarConfiguration(brokerUri, adminUri, Namespace(namespace))
+    new PulsarConfiguration(brokerUri, adminUri, Namespace(namespace), auth)
   }
 
   private def extractUri(configuration: Configuration, uriPropertyName: String): String = {
@@ -55,4 +84,20 @@ object PulsarConfiguration {
 
 case class Namespace(asString: String)
 
-case class PulsarConfiguration(brokerUri: String, adminUri: String, namespace: Namespace)
\ No newline at end of file
+sealed trait Auth
+
+object Auth {
+  def noAuth() = NoAuth
+
+  case object NoAuth extends Auth
+
+  def token(value: String) = Token(value)
+
+  case class Token(value: String) extends Auth
+
+  def basic(userId: String, password: String) = Basic(userId, password)
+
+  case class Basic(userId: String, password: String) extends Auth
+}
+
+case class PulsarConfiguration(brokerUri: String, adminUri: String, namespace: Namespace, auth: Auth = Auth.NoAuth)
\ No newline at end of file
diff --git a/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/DockerPulsarExtension.java b/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/DockerPulsarExtension.java
index 12b418676f..d535ba390d 100644
--- a/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/DockerPulsarExtension.java
+++ b/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/DockerPulsarExtension.java
@@ -70,7 +70,9 @@ public class DockerPulsarExtension implements
         return new PulsarConfiguration(
                 container.getPulsarBrokerUrl(),
                 container.getHttpServiceUrl(),
-                new Namespace("test/" + RandomStringUtils.randomAlphabetic(10)));
+                new Namespace("test/" + RandomStringUtils.randomAlphabetic(10)),
+                Auth.noAuth()
+        );
     }
 
     public PulsarConfiguration getConfiguration() {
diff --git a/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/PulsarConfigurationTest.java b/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/PulsarConfigurationTest.java
index 43eb4463a5..9fedee288f 100644
--- a/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/PulsarConfigurationTest.java
+++ b/backends-common/pulsar/src/test/java/org/apache/james/backends/pulsar/PulsarConfigurationTest.java
@@ -20,7 +20,10 @@
 package org.apache.james.backends.pulsar;
 
 import org.apache.commons.configuration2.PropertiesConfiguration;
+import org.apache.james.backends.pulsar.Auth.NoAuth$;
 import org.junit.jupiter.api.Test;
+import org.testcontainers.shaded.org.apache.commons.lang3.NotImplementedException;
+import scala.NotImplementedError;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -155,8 +158,106 @@ class PulsarConfigurationTest {
 
         configuration.addProperty("namespace", namespace);
         assertThat(PulsarConfiguration.from(configuration))
-                .isEqualTo(new PulsarConfiguration(brokerUri, adminUri, new Namespace(namespace)));
+                .isEqualTo(new PulsarConfiguration(brokerUri, adminUri, new Namespace(namespace), Auth.noAuth()));
     }
+    @Test
+    void fromShouldThrowWithTokenAuthenticationWhenTokenIsMissing() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        String brokerUri = "pulsar://localhost.test:6650/";
+        String adminUri = "http://localhost:8090";
+        String authenticationType = "token";
+
+        configuration.addProperty("broker.uri", brokerUri);
+        configuration.addProperty("admin.uri", adminUri);
+        configuration.addProperty("authentication.type", authenticationType);
+
+        String namespace = "namespace";
+
+        configuration.addProperty("namespace", namespace);
+        assertThatThrownBy(() -> PulsarConfiguration.from(configuration))
+                .isInstanceOf(IllegalStateException.class)
+                .hasMessage("You need to specify a non-empty value for " + PulsarConfiguration.AUTHENTICATION_TOKEN_PROPERTY_NAME());
+    }
+    @Test
+    void fromShouldReturnTheConfigurationWithTokenAuthenticationWhenRequiredParametersAreGiven() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        String brokerUri = "pulsar://localhost.test:6650/";
+        String adminUri = "http://localhost:8090";
+        String authenticationType = "basic";
+        String authenticationUserId = "userId";
+        String authenticationPassword = "password";
+
+        configuration.addProperty("broker.uri", brokerUri);
+        configuration.addProperty("admin.uri", adminUri);
+        configuration.addProperty("authentication.type", authenticationType);
+        configuration.addProperty("authentication.basic.userId", authenticationUserId);
+        configuration.addProperty("authentication.basic.password", authenticationPassword);
+
+        String namespace = "namespace";
+
+        configuration.addProperty("namespace", namespace);
+        assertThat(PulsarConfiguration.from(configuration))
+                .isEqualTo(new PulsarConfiguration(brokerUri, adminUri, new Namespace(namespace), Auth.basic(authenticationUserId, authenticationPassword)));
+    }
+    @Test
+    void fromShouldThrowWithBasicAuthenticationWhenUserIdIsMissing() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        String brokerUri = "pulsar://localhost.test:6650/";
+        String adminUri = "http://localhost:8090";
+        String authenticationType = "basic";
+        String authenticationUserId = "userId";
+        String authenticationPassword = "password";
+
+        configuration.addProperty("broker.uri", brokerUri);
+        configuration.addProperty("admin.uri", adminUri);
+        configuration.addProperty("authentication.type", authenticationType);
+        configuration.addProperty("authentication.basic.password", authenticationPassword);
 
+        String namespace = "namespace";
+
+        configuration.addProperty("namespace", namespace);
+        assertThatThrownBy(() -> PulsarConfiguration.from(configuration))
+                .isInstanceOf(IllegalStateException.class)
+                .hasMessage("You need to specify a non-empty value for " + PulsarConfiguration.AUTHENTICATION_BASIC_USERID_PROPERTY_NAME());
+    }
+    @Test
+    void fromShouldThrowWithBasicAuthenticationWhenPasswordIsMissing() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        String brokerUri = "pulsar://localhost.test:6650/";
+        String adminUri = "http://localhost:8090";
+        String authenticationType = "basic";
+        String authenticationUserId = "userId";
+        String authenticationPassword = "password";
+
+        configuration.addProperty("broker.uri", brokerUri);
+        configuration.addProperty("admin.uri", adminUri);
+        configuration.addProperty("authentication.type", authenticationType);
+        configuration.addProperty("authentication.basic.userId", authenticationUserId);
+
+        String namespace = "namespace";
+
+        configuration.addProperty("namespace", namespace);
 
+        assertThatThrownBy(() -> PulsarConfiguration.from(configuration))
+                .isInstanceOf(IllegalStateException.class)
+                .hasMessage("You need to specify a non-empty value for " + PulsarConfiguration.AUTHENTICATION_BASIC_PASSWORD_PROPERTY_NAME());
+    }
+
+    @Test
+    void fromShouldThrowWithUnknownAuthenticationType() {
+        PropertiesConfiguration configuration = new PropertiesConfiguration();
+        String brokerUri = "pulsar://localhost.test:6650/";
+        String adminUri = "http://localhost:8090";
+
+        configuration.addProperty("broker.uri", brokerUri);
+        configuration.addProperty("admin.uri", adminUri);
+        configuration.addProperty("authentication.type", "biscuit");
+
+        String namespace = "namespace";
+
+        configuration.addProperty("namespace", namespace);
+        assertThatThrownBy(() -> PulsarConfiguration.from(configuration))
+                .isInstanceOf(NotImplementedError.class)
+                .hasMessage("Authentication type biscuit is not implemented");
+    }
 }
\ No newline at end of file


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