Inject WebEnvironment into ODLAuthenticator 92/102092/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 16 Aug 2022 15:52:48 +0000 (17:52 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 16 Aug 2022 16:21:01 +0000 (18:21 +0200)
With the rework done in AAA-225 we no longer inject SecurityManager into
static contexts nor the WebEnvironment into the external web server.
This leads to SecurityUtils.getSubject() not being able to allocate a
subject -- and hence not working at all.

Rather than relying on static contexts, make sure we talk to the
WebEnvironment we create and use its SecurityManager to create subjects.

JIRA: AAA-215
Change-Id: I8ccc4411e31ab6b392a4be8211621fd940516935
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
aaa-shiro/impl/src/main/java/org/opendaylight/aaa/authenticator/ODLAuthenticator.java
aaa-shiro/impl/src/main/resources/OSGI-INF/blueprint/impl-blueprint.xml

index a9466e6e5565590951b5bc556d5b34a98ce176c0..b2a0934ea945be02895821a50d5004a9d85ca6a1 100644 (file)
@@ -7,34 +7,32 @@
  */
 package org.opendaylight.aaa.authenticator;
 
+import static java.util.Objects.requireNonNull;
+
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
-import javax.inject.Inject;
-import javax.inject.Singleton;
 import javax.servlet.http.HttpServletRequest;
-import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.ShiroException;
 import org.apache.shiro.authc.AuthenticationException;
 import org.apache.shiro.authc.UsernamePasswordToken;
 import org.apache.shiro.session.Session;
 import org.apache.shiro.session.UnknownSessionException;
 import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.env.WebEnvironment;
 import org.jolokia.osgi.security.Authenticator;
-import org.osgi.service.component.annotations.Component;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * AAA hook for <code>odl-jolokia</code> configured w/ <code>org.jolokia.authMode=service-all</code>.
  */
-@Singleton
-@Component(immediate = true)
 public class ODLAuthenticator implements Authenticator {
     private static final Logger LOG = LoggerFactory.getLogger(ODLAuthenticator.class);
 
-    @Inject
-    public ODLAuthenticator() {
-        // Exposed for DI
+    private final WebEnvironment env;
+
+    public ODLAuthenticator(final WebEnvironment env) {
+        this.env = requireNonNull(env);
     }
 
     @Override
@@ -49,18 +47,19 @@ public class ODLAuthenticator implements Authenticator {
 
         try {
             final String base64Creds = authorization.substring("Basic".length()).trim();
-            String credentials = new String(Base64.getDecoder().decode(base64Creds), StandardCharsets.UTF_8);
+            final String credentials = new String(Base64.getDecoder().decode(base64Creds), StandardCharsets.UTF_8);
             final String[] values = credentials.split(":", 2);
-            UsernamePasswordToken upt = new UsernamePasswordToken();
+            final UsernamePasswordToken upt = new UsernamePasswordToken();
             upt.setUsername(values[0]);
             upt.setPassword(values[1].toCharArray());
 
+            final Subject subject = new Subject.Builder(env.getSecurityManager()).buildSubject();
             try {
-                return login(upt);
+                return login(subject, upt);
             } catch (UnknownSessionException e) {
                 LOG.debug("Couldn't log in {} - logging out and retrying...", upt, e);
-                logout();
-                return login(upt);
+                logout(subject);
+                return login(subject, upt);
             }
         } catch (ArrayIndexOutOfBoundsException e) {
             // FIXME: who throws this above and why do we need to catch it? Should this be error or warn?
@@ -70,8 +69,7 @@ public class ODLAuthenticator implements Authenticator {
         return false;
     }
 
-    private static void logout() {
-        final Subject subject = SecurityUtils.getSubject();
+    private static void logout(final Subject subject) {
         try {
             subject.logout();
             Session session = subject.getSession(false);
@@ -83,8 +81,7 @@ public class ODLAuthenticator implements Authenticator {
         }
     }
 
-    private static boolean login(final UsernamePasswordToken upt) {
-        final Subject subject = SecurityUtils.getSubject();
+    private static boolean login(final Subject subject, final UsernamePasswordToken upt) {
         try {
             subject.login(upt);
         } catch (AuthenticationException e) {
index 95102a5dad344b45f317bd085fada755aa94dbab..c20dd4e515b9a47965d894e96c16c86ef922d8d6 100644 (file)
@@ -58,6 +58,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   </bean>
   <service ref="webContextSecurer" interface="org.opendaylight.aaa.web.WebContextSecurer" />
 
+  <bean id="jolokiaAuthenticator" class="org.opendaylight.aaa.authenticator.ODLAuthenticator">
+    <argument ref="webEnvironment"/>
+  </bean>
+  <service ref="jolokiaAuthenticator" interface="org.jolokia.osgi.security.Authenticator"/>
+
   <reference id="customFilterAdapterConfig"
       interface="org.opendaylight.aaa.filterchain.configuration.CustomFilterAdapterConfiguration"/>
   <reference id="webServer" interface="org.opendaylight.aaa.web.WebServer" />