Refactor Shiro/HTTP integration
[aaa.git] / aaa-shiro / impl / src / main / java / org / opendaylight / aaa / shiro / web / env / AAAWebEnvironment.java
1 /*
2  * Copyright (c) 2018 Inocybe Technologies and others.  All rights reserved.
3  * Copyright (c) 2022 PANTHEON.tech, s.r.o.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9 package org.opendaylight.aaa.shiro.web.env;
10
11 import org.apache.shiro.config.Ini;
12 import org.apache.shiro.web.env.IniWebEnvironment;
13 import org.opendaylight.aaa.api.AuthenticationService;
14 import org.opendaylight.aaa.api.TokenStore;
15 import org.opendaylight.aaa.api.password.service.PasswordHashService;
16 import org.opendaylight.aaa.cert.api.ICertificateManager;
17 import org.opendaylight.aaa.shiro.realm.KeystoneAuthRealm;
18 import org.opendaylight.aaa.shiro.realm.MDSALDynamicAuthorizationFilter;
19 import org.opendaylight.aaa.shiro.realm.MdsalRealm;
20 import org.opendaylight.aaa.shiro.realm.MoonRealm;
21 import org.opendaylight.aaa.shiro.realm.TokenAuthRealm;
22 import org.opendaylight.aaa.tokenauthrealm.auth.TokenAuthenticators;
23 import org.opendaylight.aaa.web.servlet.ServletSupport;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.aaa.app.config.rev170619.ShiroConfiguration;
26 import org.opendaylight.yangtools.util.ClassLoaderUtils;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Extends {@code BasicInitEnvironment} to provide the {@link Ini} configuration via a clustered app config,
32  * Initialization happens in the context of this class's ClassLoader, with dependencies being injected into their
33  * thread-local variables.
34  */
35 public final class AAAWebEnvironment extends IniWebEnvironment {
36     private static final Logger LOG = LoggerFactory.getLogger(AAAWebEnvironment.class);
37
38     private AAAWebEnvironment(final Ini ini) {
39         setIni(ini);
40     }
41
42     public static AAAWebEnvironment create(final ShiroConfiguration shiroConfiguration, final DataBroker dataBroker,
43             final ICertificateManager certificateManager, final AuthenticationService authenticationService,
44             final TokenAuthenticators tokenAuthenticators, final TokenStore tokenStore,
45             final PasswordHashService passwordHashService, final ServletSupport servletSupport) {
46         // Turn ShiroConfiguration into an Ini
47         final var ini = new Ini();
48
49         final var mainSection = ini.addSection("main");
50         for (var main : shiroConfiguration.nonnullMain()) {
51             mainSection.put(main.getPairKey(), main.getPairValue());
52         }
53
54         final var urlsSection = ini.addSection("urls");
55         for (var url : shiroConfiguration.nonnullUrls()) {
56             urlsSection.put(url.getPairKey(), url.getPairValue());
57         }
58
59         // Create an instance
60         final var ret = new AAAWebEnvironment(ini);
61
62         // Configure the instance with all known custom components prepared for loading via their thread locals and
63         // clean up afterwards. This needs to happen on our class loader so Shiro's ReflectionBuilder use of
64         // Class.forName() is happy.
65         ClassLoaderUtils.runWithClassLoader(AAAWebEnvironment.class.getClassLoader(), () -> {
66             try (var filterLoad = MDSALDynamicAuthorizationFilter.prepareForLoad(dataBroker);
67                  var keyStoneLoad = KeystoneAuthRealm.prepareForLoad(certificateManager, servletSupport);
68                  var mdsalLoad = MdsalRealm.prepareForLoad(passwordHashService, dataBroker);
69                  var moonLoad = MoonRealm.prepareForLoad(servletSupport);
70                  var tokenAuthLoad = TokenAuthRealm.prepareForLoad(authenticationService, tokenAuthenticators,
71                      tokenStore)) {
72                 ret.configure();
73             }
74         });
75
76         LOG.debug("AAAWebEnvironment created");
77         return ret;
78     }
79 }