Skip to content

Commit 415c0fc

Browse files
committed
Webadmin agent invalidation
Signed-off-by: sami <[email protected]>
1 parent 202379c commit 415c0fc

File tree

9 files changed

+192
-8
lines changed

9 files changed

+192
-8
lines changed

backends-common/redis/pom.xml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>org.apache.james</groupId>
6+
<artifactId>james-backends-common</artifactId>
7+
<version>3.9.0-SNAPSHOT</version>
8+
</parent>
9+
10+
<artifactId>apache-james-backends-redis</artifactId>
11+
<name>Apache James :: Backends Common :: Redis</name>
12+
13+
<dependencies>
14+
<dependency>
15+
<groupId>${james.groupId}</groupId>
16+
<artifactId>james-core</artifactId>
17+
</dependency>
18+
<dependency>
19+
<groupId>${james.groupId}</groupId>
20+
<artifactId>james-server-guice-common</artifactId>
21+
<type>test-jar</type>
22+
<scope>test</scope>
23+
</dependency>
24+
<dependency>
25+
<groupId>${james.groupId}</groupId>
26+
<artifactId>james-server-testing</artifactId>
27+
<scope>test</scope>
28+
</dependency>
29+
<dependency>
30+
<groupId>com.google.inject</groupId>
31+
<artifactId>guice</artifactId>
32+
<scope>provided</scope>
33+
</dependency>
34+
<dependency>
35+
<groupId>eu.timepit</groupId>
36+
<artifactId>refined_${scala.base}</artifactId>
37+
<scope>provided</scope>
38+
</dependency>
39+
<dependency>
40+
<groupId>io.lettuce</groupId>
41+
<artifactId>lettuce-core</artifactId>
42+
</dependency>
43+
<dependency>
44+
<groupId>io.projectreactor</groupId>
45+
<artifactId>reactor-scala-extensions_${scala.base}</artifactId>
46+
<scope>provided</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>org.apache.commons</groupId>
50+
<artifactId>commons-configuration2</artifactId>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.scalatest</groupId>
54+
<artifactId>scalatest_${scala.base}</artifactId>
55+
</dependency>
56+
<dependency>
57+
<groupId>org.testcontainers</groupId>
58+
<artifactId>testcontainers</artifactId>
59+
<scope>test</scope>
60+
</dependency>
61+
</dependencies>
62+
63+
<build>
64+
<plugins>
65+
<plugin>
66+
<groupId>net.alchim31.maven</groupId>
67+
<artifactId>scala-maven-plugin</artifactId>
68+
</plugin>
69+
</plugins>
70+
</build>
71+
</project>

examples/pom.xml.bak

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<james.protocols.groupId>${james.groupId}.protocols</james.protocols.groupId>
3939
<maven.compiler.target>1.11</maven.compiler.target>
4040
<maven.compiler.source>1.11</maven.compiler.source>
41+
<jacoco-maven-plugin.version>0.8.12</jacoco-maven-plugin.version>
4142
</properties>
4243

4344
<modules>
@@ -57,6 +58,7 @@
5758
<plugin>
5859
<groupId>org.jacoco</groupId>
5960
<artifactId>jacoco-maven-plugin</artifactId>
61+
<version>${jacoco-maven-plugin.version}</version>
6062
<executions>
6163
<execution>
6264
<id>jacoco-report</id>

server/apps/distributed-app/README.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ $ docker compose -f docker-composeOLD.yml up
128128
$ cd server/apps/distributed-app/
129129
130130
$ mvn clean install -DskipTests
131-
OR
131+
## OR
132132
$ mvn com.github.ekryd.sortpom:sortpom-maven-plugin:sort -Dsort.keepBlankLines -Dsort.predefinedSortOrder=custom_1 -DskipTests clean install
133133
134134
$ docker compose -f docker-compose.yml up -d
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
version: '3'
2+
3+
services:
4+
5+
james:
6+
depends_on:
7+
cassandra:
8+
condition: service_healthy
9+
opensearch:
10+
condition: service_started
11+
tika:
12+
condition: service_started
13+
rabbitmq:
14+
condition: service_started
15+
s3:
16+
condition: service_started
17+
image: sami7786/distributed-james-test:webadmin-invalidation
18+
volumes:
19+
- $PWD/jmap.properties:/root/conf/jmap.properties
20+
container_name: james
21+
hostname: james.local
22+
command:
23+
- --generate-keystore
24+
networks:
25+
- james
26+
ports:
27+
- "80:80"
28+
- "25:25"
29+
- "110:110"
30+
- "143:143"
31+
- "465:465"
32+
- "587:587"
33+
- "993:993"
34+
- "8000:8000"
35+
36+
opensearch:
37+
image: opensearchproject/opensearch:2.1.0
38+
environment:
39+
- discovery.type=single-node
40+
- DISABLE_INSTALL_DEMO_CONFIG=true
41+
- DISABLE_SECURITY_PLUGIN=true
42+
networks:
43+
james:
44+
aliases:
45+
- elasticsearch
46+
47+
cassandra:
48+
image: cassandra:4.1.3
49+
ports:
50+
- "9042:9042"
51+
healthcheck:
52+
test: [ "CMD", "cqlsh", "-e", "describe keyspaces" ]
53+
interval: 3s
54+
timeout: 20s
55+
retries: 5
56+
environment:
57+
- JVM_OPTS=-Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=1
58+
networks:
59+
- james
60+
61+
tika:
62+
image: apache/tika:2.8.0.0
63+
networks:
64+
- james
65+
66+
rabbitmq:
67+
image: rabbitmq:3.12.1-management
68+
ports:
69+
- "5672:5672"
70+
- "15672:15672"
71+
networks:
72+
- james
73+
74+
s3:
75+
image: registry.scality.com/cloudserver/cloudserver:8.7.25
76+
container_name: s3.docker.test
77+
environment:
78+
- SCALITY_ACCESS_KEY_ID=accessKey1
79+
- SCALITY_SECRET_ACCESS_KEY=secretKey1
80+
- S3BACKEND=mem
81+
- LOG_LEVEL=trace
82+
- REMOTE_MANAGEMENT_DISABLE=1
83+
networks:
84+
- james
85+
86+
networks:
87+
james:

server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.james.server.task.json.dto.AdditionalInformationDTO;
4141
import org.apache.james.server.task.json.dto.AdditionalInformationDTOModule;
4242
import org.apache.james.task.TaskExecutionDetails;
43+
import org.apache.james.user.api.UsersRepository;
4344
import org.apache.james.utils.ClassName;
4445
import org.apache.james.utils.ExtensionConfiguration;
4546
import org.apache.james.utils.GuiceGenericLoader;
@@ -182,11 +183,11 @@ private Optional<String> loadPublicKey(FileSystem fileSystem, Optional<String> j
182183
@Provides
183184
@Singleton
184185
public AuthenticationFilter providesAuthenticationFilter(PropertiesProvider propertiesProvider,
185-
@Named("webadmin") JwtTokenVerifier.Factory jwtTokenVerifier) throws Exception {
186+
@Named("webadmin") JwtTokenVerifier.Factory jwtTokenVerifier, UsersRepository usersRepository) throws Exception {
186187
try {
187188
Configuration configurationFile = propertiesProvider.getConfiguration("webadmin");
188189
if (configurationFile.getBoolean("jwt.enabled", DEFAULT_JWT_DISABLED)) {
189-
return new JwtFilter(jwtTokenVerifier);
190+
return new JwtFilter(jwtTokenVerifier, usersRepository);
190191
}
191192
return new NoAuthenticationFilter();
192193
} catch (FileNotFoundException e) {

server/protocols/jwt/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@
105105
<groupId>org.apache.commons</groupId>
106106
<artifactId>commons-configuration2</artifactId>
107107
</dependency>
108+
<dependency>
109+
<groupId>org.apache.james</groupId>
110+
<artifactId>james-server-data-api</artifactId>
111+
</dependency>
108112
<dependency>
109113
<groupId>org.bouncycastle</groupId>
110114
<artifactId>bcpkix-jdk15on</artifactId>

server/protocols/webadmin/webadmin-core/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@
8585
<dependency>
8686
<groupId>com.auth0</groupId>
8787
<artifactId>java-jwt</artifactId>
88-
<version>4.2.1</version> <!-- Check for the latest version -->
88+
<version>4.2.1</version>
89+
<!-- Check for the latest version -->
8990
</dependency>
9091
<dependency>
9192
<groupId>com.fasterxml.jackson.core</groupId>

server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
import javax.inject.Inject;
2828
import javax.inject.Named;
2929

30+
import org.apache.james.core.Username;
3031
import org.apache.james.jwt.JwtTokenVerifier;
32+
import org.apache.james.user.api.UsersRepository;
33+
import org.apache.james.user.api.UsersRepositoryException;
3134
import org.eclipse.jetty.http.HttpStatus;
3235

3336
import com.auth0.jwt.JWT;
@@ -45,11 +48,13 @@ public class JwtFilter implements AuthenticationFilter {
4548
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
4649
public static final String OPTIONS = "OPTIONS";
4750

51+
private final UsersRepository usersRepository;
4852
private final JwtTokenVerifier jwtTokenVerifier;
4953

5054
@Inject
51-
public JwtFilter(@Named("webadmin") JwtTokenVerifier.Factory jwtTokenVerifierFactory) {
55+
public JwtFilter(@Named("webadmin") JwtTokenVerifier.Factory jwtTokenVerifierFactory, UsersRepository usersRepository) {
5256
this.jwtTokenVerifier = jwtTokenVerifierFactory.create();
57+
this.usersRepository = usersRepository;
5358
}
5459

5560
@Override
@@ -95,10 +100,20 @@ private void checkIfNotAdminAndTypeEqualAgent(Optional<String> bearer, Request r
95100
ObjectMapper mapper = new ObjectMapper();
96101
JsonNode payloadNode = mapper.readTree(payload);
97102

103+
JsonNode usernameNode = payloadNode.get("sub");
104+
105+
try {
106+
if (!usersRepository.contains(Username.of(usernameNode != null ? usernameNode.asText() : "N/A"))) {
107+
halt(HttpStatus.NOT_FOUND_404, "User does not exist in repository.");
108+
}
109+
} catch (UsersRepositoryException e) {
110+
throw new RuntimeException(e);
111+
}
112+
98113
JsonNode typeNode = payloadNode.get("type");
99114
String type = typeNode != null ? typeNode.asText() : "N/A";
100115
if (!type.equals("agent")) {
101-
halt(HttpStatus.UNAUTHORIZED_401, "Non authorized user.Type is not agent");
116+
halt(HttpStatus.UNAUTHORIZED_401, "Non authorized user. Type is not agent");
102117
}
103118
AtomicBoolean flag = new AtomicBoolean(false);
104119

@@ -122,7 +137,7 @@ private void checkIfNotAdminAndTypeEqualAgent(Optional<String> bearer, Request r
122137
if (flag.get()) {
123138
return;
124139
}
125-
halt(HttpStatus.UNAUTHORIZED_401, "Non authorized user.Do not have permission.");
140+
halt(HttpStatus.UNAUTHORIZED_401, "Non authorized user. Do not have permission.");
126141
}
127142

128143
private void checkHeaderPresent(Optional<String> bearer) {

server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Optional;
2828

2929
import org.apache.james.jwt.JwtTokenVerifier;
30+
import org.apache.james.user.api.UsersRepository;
3031
import org.junit.jupiter.api.BeforeEach;
3132
import org.junit.jupiter.api.Test;
3233

@@ -39,11 +40,13 @@
3940
class JwtFilterTest {
4041
private JwtTokenVerifier jwtTokenVerifier;
4142
private JwtFilter jwtFilter;
43+
private UsersRepository usersRepository;
4244

4345
@BeforeEach
4446
void setUp() {
4547
jwtTokenVerifier = mock(JwtTokenVerifier.class);
46-
jwtFilter = new JwtFilter(() -> jwtTokenVerifier);
48+
usersRepository = mock(UsersRepository.class);
49+
jwtFilter = new JwtFilter(() -> jwtTokenVerifier, usersRepository);
4750
}
4851

4952
@Test

0 commit comments

Comments
 (0)