Create Filter for jetty Request 29/113029/18
authorPeter Suna <peter.suna@pantheon.tech>
Wed, 7 Aug 2024 11:53:21 +0000 (13:53 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 21 Nov 2024 20:43:08 +0000 (21:43 +0100)
The Authentication field is set to UNAUTHENTICATED because
the PaxWebServletHandler could not set this field due to
the missing remote.user attribute.

To resolve this create custom aaa filter
JettyAuthenticationLogFilter.
This filter sets the Authentication field with the user from
Basic authorization to ensure the correct name is printed
in the NCSA logs.

To enable this filter is required to activate it in Karaf console:
scr:enable org.opendaylight.aaa.filter.JettyAuthenticationLogFilter

Or activate it through configuration file:
`etc/org.opendaylight.aaa.filterchain.cfg`:

customFilterList=org.opendaylight.aaa.filter
.JettyAuthenticationLogFilter

JIRA: AAA-282
Change-Id: I26c1975ab30f0e57f0c57519d4cc1cc0becdc826
Signed-off-by: Peter Suna <peter.suna@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
aaa-jetty-auth-log-filter/pom.xml [new file with mode: 0644]
aaa-jetty-auth-log-filter/src/main/java/org/opendaylight/aaa/filter/JettyAuthenticationLogFilter.java [new file with mode: 0644]
aaa-jetty-auth-log-filter/src/test/java/org/opendaylight/aaa/filter/JettyAuthenticationLogFilterTest.java [new file with mode: 0644]
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/shiro/principal/ODLPrincipalImpl.java
artifacts/pom.xml
dependency-check/pom.xml
docs/pom.xml
features/odl-aaa-shiro/pom.xml
pom.xml

diff --git a/aaa-jetty-auth-log-filter/pom.xml b/aaa-jetty-auth-log-filter/pom.xml
new file mode 100644 (file)
index 0000000..4eee09f
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.opendaylight.aaa</groupId>
+        <artifactId>aaa-parent</artifactId>
+        <version>0.20.4-SNAPSHOT</version>
+        <relativePath>../parent</relativePath>
+    </parent>
+
+    <artifactId>aaa-jetty-auth-log-filter</artifactId>
+    <name>ODL :: aaa :: ${project.artifactId}</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-security</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-filterchain</artifactId>
+            <!-- for a String constant only -->
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>repackaged-shiro</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component.annotations</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/aaa-jetty-auth-log-filter/src/main/java/org/opendaylight/aaa/filter/JettyAuthenticationLogFilter.java b/aaa-jetty-auth-log-filter/src/main/java/org/opendaylight/aaa/filter/JettyAuthenticationLogFilter.java
new file mode 100644 (file)
index 0000000..d8cbd46
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.filter;
+
+import static org.apache.shiro.subject.support.DefaultSubjectContext.PRINCIPALS_SESSION_KEY;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.Principal;
+import java.util.Base64;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequestWrapper;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.eclipse.jetty.security.AbstractLoginService;
+import org.eclipse.jetty.security.DefaultUserIdentity;
+import org.eclipse.jetty.security.UserAuthentication;
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.Request;
+import org.opendaylight.aaa.filterchain.configuration.CustomFilterAdapterConstants;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This filter sets the Authentication field with the user from Basic authorization to ensure the correct name
+ * is printed in the Jetty NCSA logs.
+ *
+ * <p>To enable this filter is required to activate it in Karaf console:
+ * {@code scr:enable org.opendaylight.aaa.filter.JettyAuthenticationLogFilter}
+ *
+ * <p>Alternativate way to activate it activate it through {@code etc/org.opendaylight.aaa.filterchain.cfg} via setting
+ * {@code customFilterList=org.opendaylight.aaa.filter.JettyAuthenticationLogFilter}.
+ */
+@Component(enabled = false, property = CustomFilterAdapterConstants.FILTERCHAIN_FILTER + "=true")
+public final class JettyAuthenticationLogFilter implements Filter {
+    private static final Logger LOG = LoggerFactory.getLogger(JettyAuthenticationLogFilter.class);
+    private static final String BASIC = "Basic";
+    private static final String BASIC_SEP = BASIC + " ";
+
+    @Activate
+    public JettyAuthenticationLogFilter() {
+        LOG.info("Activation of JettyAuthenticationLogFilter");
+    }
+
+    @Override
+    public void init(final FilterConfig newFilterConfig) throws ServletException {
+        LOG.debug("Initializing JettyAuthenticationLogFilter");
+    }
+
+    @Override
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+            throws IOException, ServletException {
+        chain.doFilter(request, response);
+        // Apply the filter only if processing a Jetty request.
+        if (request instanceof HttpServletRequestWrapper wrapper && wrapper.getRequest() instanceof Request unwrapped) {
+            doFilter(unwrapped);
+        }
+    }
+
+    /**
+     * Set Authentication data in the Jetty request to ensure accurate output in Jetty NCSA logs.
+     *
+     * @param request Jetty request
+     */
+    private void doFilter(final Request request) {
+        if (!requestIsNullOrUnauthenticated(request)) {
+            LOG.trace("Request {} is already authenticated", request);
+            return;
+        }
+
+        // Get the session from the request, or return null if no session was used.
+        final var requestSession = request.getSession(false);
+        if (requestSession != null) {
+            // Set Authentication from Principal provided in the Session.
+            final var attribute = requestSession.getAttribute(PRINCIPALS_SESSION_KEY);
+            if (attribute instanceof PrincipalCollection collection
+                    && collection.getPrimaryPrincipal() instanceof Principal principal) {
+                final var defaultUserIdentity = new DefaultUserIdentity(null, principal, new String[0]);
+                final var userAuthentication = new UserAuthentication(BASIC, defaultUserIdentity);
+                request.setAuthentication(userAuthentication);
+                LOG.debug("Session user {} has been set in the request authentication", userAuthentication);
+                return;
+            }
+        }
+
+        // Get the user name from the request.
+        final var authorization = request.getHeader("Authorization");
+        if (authorization == null) {
+            LOG.trace("No Authorization header present in {}", request);
+            return;
+        }
+        if (!authorization.startsWith(BASIC_SEP)) {
+            LOG.trace("Request {} does not use basic authorization", request);
+            return;
+        }
+        final var userAndPassword = new String(
+            Base64.getDecoder().decode(authorization.substring(BASIC_SEP.length())), StandardCharsets.UTF_8).split(":");
+
+        // Create an Authentication class for the Jetty request based on Basic Authentication.
+        final var userPrincipal = new AbstractLoginService.UserPrincipal(userAndPassword[0], null);
+        final var defaultUserIdentity = new DefaultUserIdentity(null, userPrincipal, new String[0]);
+        final var userAuthentication = new UserAuthentication(BASIC, defaultUserIdentity);
+        request.setAuthentication(userAuthentication);
+        LOG.debug("Basic authentication user {} has been set in the request authentication", userAuthentication);
+    }
+
+    @Deactivate
+    @Override
+    public void destroy() {
+        LOG.debug("Destroying JettyAuthenticationLogFilter");
+    }
+
+    private static boolean requestIsNullOrUnauthenticated(final Request baseRequest) {
+        final var auth = baseRequest.getAuthentication();
+        return auth == null || auth == Authentication.UNAUTHENTICATED;
+    }
+}
diff --git a/aaa-jetty-auth-log-filter/src/test/java/org/opendaylight/aaa/filter/JettyAuthenticationLogFilterTest.java b/aaa-jetty-auth-log-filter/src/test/java/org/opendaylight/aaa/filter/JettyAuthenticationLogFilterTest.java
new file mode 100644 (file)
index 0000000..76da573
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.filter;
+
+import static org.apache.shiro.subject.support.DefaultSubjectContext.PRINCIPALS_SESSION_KEY;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import java.security.Principal;
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.eclipse.jetty.security.UserAuthentication;
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class JettyAuthenticationLogFilterTest {
+    private static final String SESSION_USER = "sessionUser";
+    private static final String BASIC_USER = "admin";
+
+    @Mock
+    private HttpServletRequestWrapper mockServletRequest;
+    @Mock
+    private Response mockResponse;
+    @Mock
+    private FilterChain mockFilterChain;
+    @Mock
+    private HttpSession mockHttpSession;
+    @Mock
+    private Request mockRequest;
+    @Mock
+    private Principal mockPrincipal;
+    @Mock
+    private SimplePrincipalCollection mockSimplePrincipal;
+    @Captor
+    private ArgumentCaptor<UserAuthentication> userCaptor;
+
+    private final JettyAuthenticationLogFilter logFilter = new JettyAuthenticationLogFilter();
+
+    @BeforeEach
+    void beforeEach() {
+        // Prepare environment.
+        doReturn(mockRequest).when(mockServletRequest).getRequest();
+    }
+
+    @AfterEach
+    void teardown() {
+        logFilter.destroy();
+    }
+
+    @Test
+    void testFilterWithBasicAuth() throws Exception {
+        // Setup environment only for Basic Auth without session.
+        doReturn("Basic YWRtaW46YWRtaW4=").when(mockRequest).getHeader(eq("Authorization"));
+
+        // Execute filter.
+        logFilter.doFilter(mockServletRequest, mockResponse, mockFilterChain);
+
+        // Verify correct Authentication user.
+        verify(mockRequest).setAuthentication(userCaptor.capture());
+        final var noSessionAuthentication = userCaptor.getValue();
+        assertNotNull(noSessionAuthentication);
+        assertEquals(BASIC_USER, noSessionAuthentication.getUserIdentity().getUserPrincipal().getName());
+    }
+
+    @Test
+    void testFilterWithUnauthenticatedRequestWithBasicAuth() throws Exception {
+        // Setup environment only for Basic Auth without session and Request with Unauthenticated value.
+        doReturn("Basic YWRtaW46YWRtaW4=").when(mockRequest).getHeader(eq("Authorization"));
+        doReturn(Authentication.UNAUTHENTICATED).when(mockRequest).getAuthentication();
+
+        // Execute filter.
+        logFilter.doFilter(mockServletRequest, mockResponse, mockFilterChain);
+
+        // Verify correct Authentication user.
+        verify(mockRequest).setAuthentication(userCaptor.capture());
+        final var sessionAuthentication = userCaptor.getValue();
+        assertNotNull(sessionAuthentication);
+        assertEquals(BASIC_USER, sessionAuthentication.getUserIdentity().getUserPrincipal().getName());
+    }
+
+    @Test
+    void testFilterWithSession() throws Exception {
+        // Setup environment only for Session without Basic Authentication.
+        doReturn(mockHttpSession).when(mockRequest).getSession(eq(false));
+        doReturn(mockSimplePrincipal).when(mockHttpSession).getAttribute(eq(PRINCIPALS_SESSION_KEY));
+        doReturn(mockPrincipal).when(mockSimplePrincipal).getPrimaryPrincipal();
+        doReturn(SESSION_USER).when(mockPrincipal).getName();
+
+        // Execute filter.
+        logFilter.doFilter(mockServletRequest, mockResponse, mockFilterChain);
+
+        // Verify correct Authentication user.
+        verify(mockRequest).setAuthentication(userCaptor.capture());
+        final var sessionAuthentication = userCaptor.getValue();
+        assertNotNull(sessionAuthentication);
+        assertEquals(SESSION_USER, sessionAuthentication.getUserIdentity().getUserPrincipal().getName());
+    }
+}
index 239befd762a0486f7a05e165897719a3e5b8968d..1afad167884bc7b5ee8534235ba9ac30bbac5200 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.aaa.shiro.principal;
 
+import com.google.common.base.MoreObjects;
 import java.util.Set;
 import org.opendaylight.aaa.api.Authentication;
 import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal;
@@ -16,7 +17,6 @@ import org.opendaylight.aaa.api.shiro.principal.ODLPrincipal;
  * making the auth request.
  */
 public final class ODLPrincipalImpl implements ODLPrincipal {
-
     private final String username;
     private final String domain;
     private final String userId;
@@ -35,7 +35,7 @@ public final class ODLPrincipalImpl implements ODLPrincipal {
      * @param auth Contains identifying information for the particular request.
      * @return A Principal for the given session;  essentially a DTO.
      */
-    public static ODLPrincipal createODLPrincipal(Authentication auth) {
+    public static ODLPrincipal createODLPrincipal(final Authentication auth) {
         return createODLPrincipal(auth.user(), auth.domain(), auth.userId(), auth.roles());
     }
 
@@ -48,8 +48,8 @@ public final class ODLPrincipalImpl implements ODLPrincipal {
      * @param roles The roles associated with <code>username</code>@<code>domain</code>
      * @return A Principal for the given session;  essentially a DTO.
      */
-    public static ODLPrincipal createODLPrincipal(String username, String domain,
-                                           String userId, Set<String> roles) {
+    public static ODLPrincipal createODLPrincipal(final String username, final String domain,
+                                           final String userId, final Set<String> roles) {
 
         return new ODLPrincipalImpl(username, domain, userId, roles);
     }
@@ -62,33 +62,43 @@ public final class ODLPrincipalImpl implements ODLPrincipal {
      * @param userId The unique key for <code>username</code>
      * @return A Principal for the given session;  essentially a DTO.
      */
-    public static ODLPrincipal createODLPrincipal(String username, String domain,
-                                                  String userId) {
+    public static ODLPrincipal createODLPrincipal(final String username, final String domain,
+                                                  final String userId) {
         return ODLPrincipalImpl.createODLPrincipal(username, domain, userId, null);
     }
 
     @Override
     public String getUsername() {
-        return this.username;
+        return username;
     }
 
     @Override
     public String getDomain() {
-        return this.domain;
+        return domain;
     }
 
     @Override
     public String getUserId() {
-        return this.userId;
+        return userId;
     }
 
     @Override
     public Set<String> getRoles() {
-        return this.roles;
+        return roles;
     }
 
     @Override
     public String getName() {
         return getUserId();
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).omitNullValues()
+            .add("userId", userId)
+            .add("username", username)
+            .add("domain", domain)
+            .add("roles", roles)
+            .toString();
+    }
 }
index 5d352781e511c53ea71a2ea7e9fbdbac92fa9795..d9a8076dfbf7d10279fb9a5242277f23cb6fbb5f 100644 (file)
                 <type>cfg</type>
                 <classifier>config</classifier>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.aaa</groupId>
+                <artifactId>aaa-jetty-auth-log-filter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
 
             <dependency>
                 <groupId>${project.groupId}</groupId>
index 4ae972358cff7ba98a825d89e866561448e0e5ec..e0ef7c434799a1383e211b98675a37f05a196cc8 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>aaa-idm-store-h2</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-jetty-auth-log-filter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>aaa-password-service-api</artifactId>
index 29ff41d53a406b4d83f3b141873e82c73d66ad80..876c8edc218b46b8350eb9c24667f9f522a7b49e 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>aaa-filterchain</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>aaa-jetty-auth-log-filter</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>${project.groupId}</groupId>
index bd0673f5988760db2b48ebd0d97d5a946fe85c18..2a168123bb8e6ca9c7e8447f89a6c67cc81880f5 100644 (file)
 
     <dependencies>
         <dependency>
-            <groupId>org.opendaylight.aaa</groupId>
-            <artifactId>odl-aaa-password-service</artifactId>
-            <classifier>features</classifier>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>odl-aaa-api</artifactId>
             <type>xml</type>
+            <classifier>features</classifier>
         </dependency>
-
         <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>odl-jolokia</artifactId>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>odl-aaa-cert</artifactId>
+            <type>xml</type>
             <classifier>features</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>odl-aaa-encryption-service</artifactId>
             <type>xml</type>
+            <classifier>features</classifier>
         </dependency>
-
-        <!-- Existing AAA infrastructure -->
         <dependency>
             <groupId>org.opendaylight.aaa</groupId>
-            <artifactId>odl-aaa-web</artifactId>
+            <artifactId>odl-aaa-password-service</artifactId>
             <classifier>features</classifier>
             <type>xml</type>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.aaa</groupId>
-            <artifactId>aaa-shiro</artifactId>
+            <artifactId>odl-aaa-web</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
         </dependency>
         <dependency>
-          <groupId>org.opendaylight.aaa</groupId>
-          <artifactId>aaa-shiro-api</artifactId>
+            <groupId>org.opendaylight.odlparent</groupId>
+            <artifactId>odl-karaf-feat-jetty</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
         </dependency>
+
         <dependency>
-            <groupId>org.opendaylight.aaa</groupId>
-            <artifactId>odl-aaa-encryption-service</artifactId>
-            <type>xml</type>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>odl-jolokia</artifactId>
             <classifier>features</classifier>
+            <type>xml</type>
         </dependency>
+
+        <!-- Existing AAA infrastructure -->
         <dependency>
             <groupId>org.opendaylight.aaa</groupId>
             <artifactId>aaa-filterchain</artifactId>
         </dependency>
         <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>odl-aaa-api</artifactId>
-            <type>xml</type>
-            <classifier>features</classifier>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-jetty-auth-log-filter</artifactId>
         </dependency>
         <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>odl-aaa-cert</artifactId>
-            <type>xml</type>
-            <classifier>features</classifier>
+            <groupId>org.opendaylight.aaa</groupId>
+            <artifactId>aaa-shiro</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>org.opendaylight.aaa</groupId>
+          <artifactId>aaa-shiro-api</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.aaa</groupId>
             <type>xml</type>
             <classifier>aaa-datastore-config</classifier>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.odlparent</groupId>
-            <artifactId>odl-karaf-feat-jetty</artifactId>
-            <type>xml</type>
-            <classifier>features</classifier>
-        </dependency>
 
         <!--H2 Store -->
         <dependency>
diff --git a/pom.xml b/pom.xml
index ff79a3eb3b52a2b99a73d8ef03f24e8c5515a73d..e336d53e90a5895c6377cca905d477df6d951b07 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
     <module>aaa-cli-jar</module>
     <module>aaa-filterchain</module>
     <module>aaa-idm-store-h2</module>
+    <module>aaa-jetty-auth-log-filter</module>
     <module>aaa-password-service</module>
     <module>artifacts</module>
     <module>features</module>