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

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


The following commit(s) were added to refs/heads/master by this push:
     new 920c19b0e8 JAMES-3897: Implement CrowdsecHttpClient (#1788)
920c19b0e8 is described below

commit 920c19b0e8268223171d3d2958c97a85d224fcc3
Author: vtbui <[email protected]>
AuthorDate: Mon Nov 27 11:19:42 2023 +0700

    JAMES-3897: Implement CrowdsecHttpClient (#1788)
---
 third-party/crowdsec/pom.xml                       |  57 +++++----
 .../sample-configuration/crowdsec.properties       |   2 +
 .../sample-configuration/extensions.properties     |   1 +
 .../james/model/CrowdsecClientConfiguration.java   |  61 ++++++++++
 .../org/apache/james/model/CrowdsecDecision.java   |  28 +++++
 .../org/apache/james/model/CrowdsecHttpClient.java |  96 ++++++++++++++++
 .../org/apache/james/module/CrowdsecModule.java    |  46 ++++++++
 .../james/CrowdsecDecisionDeserializerTest.java    |  51 ++++++++
 .../java/org/apache/james/CrowdsecExtension.java   |   5 +-
 .../org/apache/james/CrowdsecHttpClientTest.java   | 128 +++++++++++++++++++++
 10 files changed, 453 insertions(+), 22 deletions(-)

diff --git a/third-party/crowdsec/pom.xml b/third-party/crowdsec/pom.xml
index 65f039d456..b839b1ba6f 100644
--- a/third-party/crowdsec/pom.xml
+++ b/third-party/crowdsec/pom.xml
@@ -25,13 +25,9 @@
         <version>3.9.0-SNAPSHOT</version>
     </parent>
 
-    <artifactId>crowdsec</artifactId>
+    <artifactId>apache-james-crowdsec</artifactId>
     <name>Apache James :: Third Party :: Crowdsec</name>
-    <description>Crowdsec Java client (HTTP) and testing 
utilities</description>
-
-    <properties>
-        <james.baseVersion>${project.version}</james.baseVersion>
-    </properties>
+    <description>Crowdsec extension for Apache James</description>
 
     <dependencies>
         <dependency>
@@ -41,45 +37,65 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-configuration</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>testing-base</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.datatype</groupId>
             <artifactId>jackson-datatype-jdk8</artifactId>
-            <scope>test</scope>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.github.fge</groupId>
             <artifactId>throwing-lambdas</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-configuration2</artifactId>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.james</groupId>
-            <artifactId>james-server-testing</artifactId>
-            <scope>test</scope>
+            <groupId>io.projectreactor.netty</groupId>
+            <artifactId>reactor-netty-http</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
-            <scope>test</scope>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-configuration2</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter</artifactId>
-            <version>RELEASE</version>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>james-server-testing</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>log4j-over-slf4j</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.testcontainers</groupId>
@@ -87,5 +103,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-
 </project>
diff --git a/third-party/crowdsec/sample-configuration/crowdsec.properties 
b/third-party/crowdsec/sample-configuration/crowdsec.properties
new file mode 100644
index 0000000000..ce0863c4a0
--- /dev/null
+++ b/third-party/crowdsec/sample-configuration/crowdsec.properties
@@ -0,0 +1,2 @@
+crowdsecUrl=http://127.0.0.1:8082/v1
+apiKey=default_api_key
\ No newline at end of file
diff --git a/third-party/crowdsec/sample-configuration/extensions.properties 
b/third-party/crowdsec/sample-configuration/extensions.properties
new file mode 100644
index 0000000000..e17656b5f7
--- /dev/null
+++ b/third-party/crowdsec/sample-configuration/extensions.properties
@@ -0,0 +1 @@
+guice.extension.module=org.apache.james.module.CrowdsecModule
\ No newline at end of file
diff --git 
a/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecClientConfiguration.java
 
b/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecClientConfiguration.java
new file mode 100644
index 0000000000..31ffc89c9f
--- /dev/null
+++ 
b/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecClientConfiguration.java
@@ -0,0 +1,61 @@
+/****************************************************************
+ * 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.model;
+
+import java.net.URL;
+import java.time.Duration;
+import java.util.Optional;
+
+import org.apache.commons.configuration2.Configuration;
+
+import com.github.fge.lambdas.Throwing;
+
+
+public class CrowdsecClientConfiguration {
+    public static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(5L);
+    public static final String DEFAULT_API_KEY = "default_api_key";
+
+    private final URL url;
+    private final String apiKey;
+
+    public static CrowdsecClientConfiguration from(Configuration config) {
+        URL crowdsecUrl = Optional.ofNullable(config.getString("crowdsecUrl", 
null))
+            .filter(s -> !s.isEmpty())
+            .map(Throwing.function(URL::new))
+            .orElseThrow(() -> new IllegalArgumentException("Crowdsec's url is 
invalid."));
+
+        String apiKey = Optional.of(config.getString("apiKey"))
+            .orElseThrow(() -> new IllegalArgumentException("Missing 
apiKey!"));
+        return new CrowdsecClientConfiguration(crowdsecUrl, apiKey);
+    }
+
+    public CrowdsecClientConfiguration(URL url, String apiKey) {
+        this.url = url;
+        this.apiKey = apiKey;
+    }
+
+    public URL getUrl() {
+        return this.url;
+    }
+
+    public String getApiKey() {
+        return this.apiKey;
+    }
+}
diff --git 
a/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecDecision.java
 
b/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecDecision.java
index b3a3f2ea7c..c5d10efc3f 100644
--- 
a/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecDecision.java
+++ 
b/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecDecision.java
@@ -57,6 +57,34 @@ public class CrowdsecDecision {
         this.duration = duration;
     }
 
+    public Duration getDuration() {
+        return duration;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public String getOrigin() {
+        return origin;
+    }
+
+    public String getScenario() {
+        return scenario;
+    }
+
+    public String getScope() {
+        return scope;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
     public final boolean equals(Object o) {
         if (!(o instanceof CrowdsecDecision)) {
             return false;
diff --git 
a/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecHttpClient.java
 
b/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecHttpClient.java
new file mode 100644
index 0000000000..e537d158d1
--- /dev/null
+++ 
b/third-party/crowdsec/src/main/java/org/apache/james/model/CrowdsecHttpClient.java
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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.model;
+
+import static 
org.apache.james.model.CrowdsecClientConfiguration.DEFAULT_TIMEOUT;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.http.HttpStatus;
+import org.apache.http.entity.ContentType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.google.common.collect.ImmutableList;
+
+import io.netty.handler.codec.http.HttpHeaderNames;
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+
+public class CrowdsecHttpClient {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(CrowdsecHttpClient.class);
+    private static final String GET_DECISION = "/decisions";
+
+    private final HttpClient httpClient;
+    private final ObjectMapper mapper;
+
+    @Inject
+    public CrowdsecHttpClient(CrowdsecClientConfiguration configuration) {
+        this.httpClient = buildReactorNettyHttpClient(configuration);
+        this.mapper = new ObjectMapper().registerModule(new Jdk8Module());
+    }
+
+    public Mono<List<CrowdsecDecision>> getCrowdsecDecisions() {
+        return httpClient.get()
+            .uri(GET_DECISION)
+            .responseSingle((response, body) -> {
+                switch (response.status().code()) {
+                    case HttpStatus.SC_OK:
+                        return 
body.asString().map(this::parseCrowdsecDecisions);
+                    case HttpStatus.SC_FORBIDDEN:
+                        return Mono.error(new RuntimeException("Invalid 
api-key bouncer"));
+                    case HttpStatus.SC_NOT_FOUND:
+                        return Mono.error(new RuntimeException("Crowdsec url 
not found"));
+                    default:
+                        return Mono.error(new RuntimeException("Request failed 
with status code " + response.status().code()));
+                }
+            });
+    }
+
+    private List<CrowdsecDecision> parseCrowdsecDecisions(String json) {
+        if (noCrowdsecDecision(json)) {
+            return ImmutableList.of();
+        } else {
+            try {
+                return mapper.readValue(json, new TypeReference<>() {});
+            } catch (JsonProcessingException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private static boolean noCrowdsecDecision(String json) {
+        return json.equals("null");
+    }
+
+    private HttpClient buildReactorNettyHttpClient(CrowdsecClientConfiguration 
configuration) {
+        return HttpClient.create()
+            .responseTimeout(DEFAULT_TIMEOUT)
+            .baseUrl(configuration.getUrl().toString())
+            .headers(headers -> headers.add("X-Api-Key", 
configuration.getApiKey()))
+            .headers(headers -> headers.add(HttpHeaderNames.ACCEPT, 
ContentType.APPLICATION_JSON.getMimeType()));
+    }
+}
diff --git 
a/third-party/crowdsec/src/main/java/org/apache/james/module/CrowdsecModule.java
 
b/third-party/crowdsec/src/main/java/org/apache/james/module/CrowdsecModule.java
new file mode 100644
index 0000000000..05df517650
--- /dev/null
+++ 
b/third-party/crowdsec/src/main/java/org/apache/james/module/CrowdsecModule.java
@@ -0,0 +1,46 @@
+/****************************************************************
+ * 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.module;
+
+import java.io.FileNotFoundException;
+
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.james.model.CrowdsecClientConfiguration;
+import org.apache.james.model.CrowdsecHttpClient;
+import org.apache.james.utils.PropertiesProvider;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+public class CrowdsecModule extends AbstractModule {
+
+    @Provides
+    @Singleton
+    public CrowdsecClientConfiguration 
crowdsecClientConfiguration(PropertiesProvider propertiesProvider) throws 
ConfigurationException, FileNotFoundException {
+        return 
CrowdsecClientConfiguration.from(propertiesProvider.getConfiguration("crowdsec"));
+    }
+
+    @Provides
+    @Singleton
+    public CrowdsecHttpClient crowdsecHttpClient(CrowdsecClientConfiguration 
crowdsecClientConfiguration) {
+        return new CrowdsecHttpClient(crowdsecClientConfiguration);
+    }
+}
diff --git 
a/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecDecisionDeserializerTest.java
 
b/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecDecisionDeserializerTest.java
new file mode 100644
index 0000000000..88ebfc0776
--- /dev/null
+++ 
b/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecDecisionDeserializerTest.java
@@ -0,0 +1,51 @@
+/****************************************************************
+ * 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;
+
+import java.time.Duration;
+import java.util.List;
+
+import org.apache.james.model.CrowdsecDecision;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+
+class CrowdsecDecisionDeserializerTest {
+    @Test
+    void deserializeCrowdsecDecisionTest() throws Exception {
+        String json = "[\n{\n  \"duration\": \"3h47m14.654059061s\",\n  
\"id\": 3,\n  \"origin\": \"cscli\",\n  \"scenario\": \"manual 'ban' from 
'localhost'\",\n  \"scope\": \"Ip\",\n  \"type\": \"ban\",\n  \"value\": 
\"1.1.2.54\"\n}\n]";
+        ObjectMapper objectMapper = (new ObjectMapper()).registerModule(new 
Jdk8Module());
+        List<CrowdsecDecision> decisions = objectMapper.readValue(json, new 
TypeReference<>() {});
+
+        Assertions.assertThat(decisions.get(0))
+            .isEqualTo(CrowdsecDecision.builder()
+                .duration(Duration.parse("PT3h47m14.654059061s"))
+                .id(3L)
+                .origin("cscli")
+                .scenario("manual 'ban' from 'localhost'")
+                .scope("Ip")
+                .value("1.1.2.54")
+                .type("ban")
+                .build());
+    }
+}
\ No newline at end of file
diff --git 
a/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecExtension.java 
b/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecExtension.java
index 45edba2068..f683c5673e 100644
--- a/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecExtension.java
+++ b/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecExtension.java
@@ -28,9 +28,12 @@ import org.junit.jupiter.api.extension.ExtensionContext;
 import org.testcontainers.containers.GenericContainer;
 import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
 
+import com.google.common.collect.ImmutableList;
+
 public class CrowdsecExtension implements GuiceModuleTestExtension {
     public static final Duration STARTUP_TIMEOUT = Duration.ofMinutes(5);
     public static final int CROWDSEC_PORT = 8080;
+    public static final int EXPOSED_PORT = 8082;
     public static final String CROWDSEC_IMAGE = 
"crowdsecurity/crowdsec:v1.5.4";
 
     private final GenericContainer<?> crowdsecContainer;
@@ -40,7 +43,7 @@ public class CrowdsecExtension implements 
GuiceModuleTestExtension {
             .withCreateContainerCmdModifier(cmd -> 
cmd.withName("james-crowdsec-test-" + UUID.randomUUID()))
             .withExposedPorts(CROWDSEC_PORT)
             .withStartupTimeout(STARTUP_TIMEOUT)
-            .waitingFor(new 
HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));;
+            .waitingFor(new 
HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND));
     }
 
     @Override
diff --git 
a/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecHttpClientTest.java
 
b/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecHttpClientTest.java
new file mode 100644
index 0000000000..38cf40a08f
--- /dev/null
+++ 
b/third-party/crowdsec/src/test/java/org/apache/james/CrowdsecHttpClientTest.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;
+
+import static org.apache.james.CrowdsecExtension.CROWDSEC_PORT;
+import static 
org.apache.james.model.CrowdsecClientConfiguration.DEFAULT_API_KEY;
+import static org.apache.james.model.CrowdsecDecision.BAN;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.james.model.CrowdsecClientConfiguration;
+import org.apache.james.model.CrowdsecDecision;
+import org.apache.james.model.CrowdsecHttpClient;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class CrowdsecHttpClientTest {
+    @RegisterExtension
+    static CrowdsecExtension crowdsecExtension = new CrowdsecExtension();
+
+    @BeforeAll
+    static void setUp() throws IOException, InterruptedException {
+        crowdsecExtension.getCrowdsecContainer().execInContainer("cscli", 
"bouncer", "add", "bouncer", "-k", DEFAULT_API_KEY);
+    }
+
+    @Test
+    void getDecisionsWhenBanningAnIP() throws IOException, 
InterruptedException {
+        banIP("--ip", "192.168.0.4");
+        int port = 
crowdsecExtension.getCrowdsecContainer().getMappedPort(CROWDSEC_PORT);
+        CrowdsecClientConfiguration config = new 
CrowdsecClientConfiguration(new URL("http://localhost:"; + port + "/v1"), 
DEFAULT_API_KEY);
+        CrowdsecHttpClient httpClient = new CrowdsecHttpClient(config);
+        List<CrowdsecDecision> decisions = 
httpClient.getCrowdsecDecisions().block();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(decisions).hasSize(1);
+            
softly.assertThat(decisions.get(0).getValue().equals("192.168.0.4") && 
decisions.get(0).getType().equals(BAN));
+        });
+    }
+
+    @Test
+    void getDecisionsWhenBanningAnIPRange() throws IOException, 
InterruptedException {
+        banIP("--range", "192.168.0.0/16");
+        int port = 
crowdsecExtension.getCrowdsecContainer().getMappedPort(CROWDSEC_PORT);
+        CrowdsecClientConfiguration config = new 
CrowdsecClientConfiguration(new URL("http://localhost:"; + port + "/v1"), 
DEFAULT_API_KEY);
+        CrowdsecHttpClient httpClient = new CrowdsecHttpClient(config);
+        List<CrowdsecDecision> decisions = 
httpClient.getCrowdsecDecisions().block();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(decisions).hasSize(1);
+            
softly.assertThat(decisions.get(0).getValue().equals("192.168.0.0/16") && 
decisions.get(0).getType().equals(BAN));
+        });
+    }
+
+    @Test
+    void getDecisionsWithWrongApiKey() throws IOException, 
InterruptedException {
+        banIP("--range", "192.168.0.0/16");
+        int port = 
crowdsecExtension.getCrowdsecContainer().getMappedPort(CROWDSEC_PORT);
+        CrowdsecClientConfiguration config = new 
CrowdsecClientConfiguration(new URL("http://localhost:"; + port + "/v1"), 
"wrong-key");
+        CrowdsecHttpClient httpClient = new CrowdsecHttpClient(config);
+
+        assertThatThrownBy(() -> httpClient.getCrowdsecDecisions().block())
+            .hasMessage("Invalid api-key bouncer");
+    }
+
+    @Test
+    void getDecisionsWithWrongCrowdsecUrl() throws IOException, 
InterruptedException {
+        banIP("--range", "192.168.0.0/16");
+        int port = 
crowdsecExtension.getCrowdsecContainer().getMappedPort(CROWDSEC_PORT);
+        CrowdsecClientConfiguration config = new 
CrowdsecClientConfiguration(new URL("http://localhost:"; + port + "/v2"), 
DEFAULT_API_KEY);
+        CrowdsecHttpClient httpClient = new CrowdsecHttpClient(config);
+
+        assertThatThrownBy(() -> httpClient.getCrowdsecDecisions().block())
+            .hasMessage("Crowdsec url not found");
+    }
+
+    @Test
+    void getDecisionsWhenNoBanning() throws IOException {
+        int port = 
crowdsecExtension.getCrowdsecContainer().getMappedPort(CROWDSEC_PORT);
+        CrowdsecClientConfiguration config = new 
CrowdsecClientConfiguration(new URL("http://localhost:"; + port + "/v1"), 
DEFAULT_API_KEY);
+        CrowdsecHttpClient httpClient = new CrowdsecHttpClient(config);
+        List<CrowdsecDecision> decisions = 
httpClient.getCrowdsecDecisions().block();
+
+        assertThat(decisions).hasSize(0);
+    }
+
+    @Test
+    void getDecisionsWhenBanningMultipleIP() throws IOException, 
InterruptedException {
+        banIP("--ip", "192.168.0.4");
+        banIP("--ip", "192.168.0.5");
+        int port = 
crowdsecExtension.getCrowdsecContainer().getMappedPort(CROWDSEC_PORT);
+        CrowdsecClientConfiguration config = new 
CrowdsecClientConfiguration(new URL("http://localhost:"; + port + "/v1"), 
DEFAULT_API_KEY);
+        CrowdsecHttpClient httpClient = new CrowdsecHttpClient(config);
+        List<CrowdsecDecision> decisions = 
httpClient.getCrowdsecDecisions().block();
+
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(decisions).hasSize(2);
+            
softly.assertThat(decisions.get(0).getValue().equals("192.168.0.4") && 
decisions.get(0).getType().equals(BAN));
+            
softly.assertThat(decisions.get(1).getValue().equals("192.168.0.5") && 
decisions.get(1).getType().equals(BAN));
+        });
+    }
+
+    private static void banIP(String type, String value) throws IOException, 
InterruptedException {
+        crowdsecExtension.getCrowdsecContainer().execInContainer("cscli", 
"decision", "add", type, value);
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to