Skip to content

Commit

Permalink
fix in services unregistration
Browse files Browse the repository at this point in the history
wip
  • Loading branch information
salvatore-coppola committed Feb 21, 2025
1 parent ddef8d6 commit cc2f172
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
import java.util.Optional;
import java.util.Set;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import org.eclipse.kura.audit.AuditConstants;
import org.eclipse.kura.audit.AuditContext;
import org.eclipse.kura.internal.rest.auth.dto.AuthenticationInfoDTO;
Expand All @@ -42,6 +38,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.eclipse.kura.web.session.BaseSecurityHandler;
import org.eclipse.kura.web.session.CreateSessionSecurityHandler;
import org.eclipse.kura.web.session.HttpServletContextHelper;
import org.eclipse.kura.web.session.HttpSessionTracker;
import org.eclipse.kura.web.session.RoutingSecurityHandler;
import org.eclipse.kura.web.session.SecurityHandler;
import org.eclipse.kura.web.session.SessionAutorizationSecurityHandler;
Expand All @@ -83,7 +84,6 @@
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventProperties;
import org.osgi.service.http.NamespaceException;
import org.osgi.service.servlet.context.ServletContextHelper;
import org.osgi.service.servlet.whiteboard.HttpWhiteboardConstants;
import org.slf4j.Logger;
Expand All @@ -93,11 +93,13 @@
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionIdListener;
import jakarta.servlet.http.HttpSessionListener;

public class Console implements SelfConfiguringComponent {

private static final String SESSION_CONTEXT_NAME = "sessionContext";

private static final String RESOURCE_CONTEXT_NAME = "resourceContext";

private static final String SESSION = "/session";
Expand All @@ -117,6 +119,8 @@ public class Console implements SelfConfiguringComponent {
private static final String PASSWORD_AUTH_PATH = LOGIN_MODULE_PATH + "/password";
private static final String CERT_AUTH_PATH = LOGIN_MODULE_PATH + "/cert";

private static final String XSRF_PATH = "/xsrf";

private static final Logger logger = LoggerFactory.getLogger(Console.class);

private String appRoot;
Expand All @@ -138,6 +142,9 @@ public class Console implements SelfConfiguringComponent {
private final Set<ServiceRegistration<ResourcesService>> resources = new CopyOnWriteArraySet<>();
private final Set<ServiceRegistration<Servlet>> servlets = new CopyOnWriteArraySet<>();

private final Set<String> authenticationPaths = new HashSet<>(
Arrays.asList(AUTH_PATH, PASSWORD_AUTH_PATH, CERT_AUTH_PATH));

private BundleContext bundleContext;

private static Console instance;
Expand Down Expand Up @@ -268,14 +275,11 @@ private void doUpdate(ConsoleOptions options) {
setAppRoot(options.getAppRoot());
setSessionMaxInactiveInterval(options.getSessionMaxInactivityInterval());

try {
initHTTPService();
} catch (NamespaceException e) {
logger.warn("Error Registering Web Resources", e);
}
initResourcesAndServlets();

}

protected void deactivate(BundleContext context) {
protected void deactivate() {
logger.info("deactivate...");

unregisterAll();
Expand All @@ -289,13 +293,16 @@ protected void deactivate(BundleContext context) {

private synchronized void unregisterAll() {

this.wiresBlinkService.stop();
this.eventService.stop();

this.contexts.forEach(ServiceRegistration::unregister);
this.resources.forEach(ServiceRegistration::unregister);
this.servlets.forEach(ServiceRegistration::unregister);

this.wiresBlinkService.stop();

this.eventService.stop();
this.contexts.clear();
this.resources.clear();
this.servlets.clear();

}

Expand Down Expand Up @@ -326,8 +333,8 @@ public AuditContext initAuditContext(final HttpServletRequest req) {

final AuditContext auditContext;

if (rawAuditContext instanceof AuditContext) {
auditContext = ((AuditContext) rawAuditContext).copy();
if (rawAuditContext instanceof AuditContext context) {
auditContext = context.copy();
auditContext.getProperties().remove("rpc.method");
auditContext.getProperties().put(AuditConstants.KEY_IP.getValue(), requestIp);
} else {
Expand Down Expand Up @@ -403,14 +410,12 @@ private void updateAuditContext(final HttpSession session) {

final Object sessionAuditContext = session.getAttribute(Attributes.AUDIT_CONTEXT.getValue());

if (sessionAuditContext instanceof AuditContext) {
((AuditContext) sessionAuditContext).getProperties().put("session.id", id);
if (sessionAuditContext instanceof AuditContext auditContext) {
auditContext.getProperties().put("session.id", id);
}

}

final Set<String> authenticationPaths = new HashSet<>(Arrays.asList(AUTH_PATH, PASSWORD_AUTH_PATH, CERT_AUTH_PATH));

private SecurityHandler createSessionHandlerChain() {

final Set<String> eventPaths = new HashSet<>(Arrays.asList(DENALI_MODULE_PATH + EVENT_PATH, "/sse"));
Expand All @@ -429,7 +434,7 @@ private SecurityHandler createSessionHandlerChain() {
final RoutingSecurityHandler routingHandler = new RoutingSecurityHandler(
defaultHandler.sendErrorOnFailure(401));

// exception on authentication paths, allow access without authenticaton but
// exception on authentication paths, allow access without authentication but
// create a session
routingHandler.addRouteHandler(this.authenticationPaths::contains,
chain(baseHandler, new CreateSessionSecurityHandler()));
Expand All @@ -446,13 +451,13 @@ private SecurityHandler createSessionHandlerChain() {
// exception on login session and xsrf path, like default but without locked
// session checking
routingHandler.addRouteHandler(
Arrays.asList(LOGIN_MODULE_PATH + SESSION, LOGIN_MODULE_PATH + "/xsrf")::contains,
Arrays.asList(LOGIN_MODULE_PATH + SESSION, LOGIN_MODULE_PATH + XSRF_PATH)::contains,
chain(baseHandler, sessionAuthHandler, sessionExpirationHandler));

return routingHandler;
}

private synchronized void initHTTPService() throws NamespaceException {
private synchronized void initResourcesAndServlets() {

this.eventService = new GwtEventServiceImpl();
this.wiresBlinkService = new WiresBlinkServlet();
Expand All @@ -463,6 +468,10 @@ private synchronized void initHTTPService() throws NamespaceException {
registerContextHelper(RESOURCE_CONTEXT_NAME, "/", resourceContextHelper, 5);
registerContextHelper(SESSION_CONTEXT_NAME, "/", sessionContextHelper, 10);

HttpSessionTracker sessionTracker = new HttpSessionTracker();

registerListeners(sessionTracker, SESSION_CONTEXT_NAME);

registerResources(ADMIN_ROOT + "/*", "www", new AdminResources(), RESOURCE_CONTEXT_NAME);
registerResources(AUTH_PATH, "www/auth.html", new AuthorizationResources(), SESSION_CONTEXT_NAME);
registerResources(CONSOLE_PATH, "www/denali.html", new ConsoleResources(), SESSION_CONTEXT_NAME);
Expand Down Expand Up @@ -491,9 +500,9 @@ private synchronized void initHTTPService() throws NamespaceException {

registerServlet("loginSessionService", LOGIN_MODULE_PATH + SESSION, new GwtSessionServiceImpl(this.userManager),
SESSION_CONTEXT_NAME);
registerServlet("xsrfLoginServlet", LOGIN_MODULE_PATH + "/xsrf", new GwtSecurityTokenServiceImpl(),
registerServlet("xsrfLoginServlet", LOGIN_MODULE_PATH + XSRF_PATH, new GwtSecurityTokenServiceImpl(),
SESSION_CONTEXT_NAME);
registerServlet("xsrfDenaliServlet", DENALI_MODULE_PATH + "/xsrf", new GwtSecurityTokenServiceImpl(),
registerServlet("xsrfDenaliServlet", DENALI_MODULE_PATH + XSRF_PATH, new GwtSecurityTokenServiceImpl(),
SESSION_CONTEXT_NAME);
registerServlet("statusService", DENALI_MODULE_PATH + "/status", new GwtStatusServiceImpl(),
SESSION_CONTEXT_NAME);
Expand Down Expand Up @@ -536,49 +545,94 @@ private synchronized void initHTTPService() throws NamespaceException {
this.eventService.start();
}

private void registerListeners(HttpSessionTracker sessionTracker, String contextHelperName) {
Map<String, Object> props = new HashMap<>();

String contextHelperSelector = "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "="
+ contextHelperName + ")";

props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true");
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextHelperSelector);

ServiceRegistration<HttpSessionListener> listenerService1 = this.bundleContext
.registerService(HttpSessionListener.class, sessionTracker, new Hashtable<>(props));

ServiceRegistration<HttpSessionIdListener> listenerService2 = this.bundleContext
.registerService(HttpSessionIdListener.class, sessionTracker, new Hashtable<>(props));

ServiceRegistration<HttpSessionAttributeListener> listenerService3 = this.bundleContext
.registerService(HttpSessionAttributeListener.class, sessionTracker, new Hashtable<>(props));

logger.debug("registered listener with id: {} , contextHelperName: {}", //
listenerService1.getReference().getProperty(Constants.SERVICE_ID), contextHelperName);

logger.debug("registered listener with id: {} , contextHelperName: {}", //
listenerService2.getReference().getProperty(Constants.SERVICE_ID), contextHelperName);

logger.debug("registered listener with id: {} , contextHelperName: {}", //
listenerService3.getReference().getProperty(Constants.SERVICE_ID), contextHelperName);

}

private void registerContextHelper(String contextName, String contextPath, ServletContextHelper contextHelper,
int ranking) {
Map<String, Object> props = new HashMap<>();

props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, contextName);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, contextPath);
props.put(Constants.SERVICE_RANKING, ranking);
props.put(Constants.SERVICE_SCOPE, Constants.SCOPE_BUNDLE);

ServiceRegistration<ServletContextHelper> contextService = this.bundleContext
.registerService(ServletContextHelper.class, contextHelper, new Hashtable<>(props));

this.contexts.add(contextService);

logger.debug("registered context helper with id: {} , name: {} , path {}", //
contextService.getReference().getProperty(Constants.SERVICE_ID), contextName, contextPath);
}

private void registerResources(String pattern, String prefix, ResourcesService resourcesService,
String contextHelperName) {
Map<String, Object> props = new HashMap<>();

String contextHelperSelector = "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "="
+ contextHelperName + ")";

props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, pattern);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, prefix);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
"(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + contextHelperName + ")");
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextHelperSelector);

ServiceRegistration<ResourcesService> resourcesS = this.bundleContext.registerService(ResourcesService.class,
resourcesService, new Hashtable<>(props));

this.resources.add(resourcesS);

logger.debug("registered resource with id: {} , pattern: {} , prefix {} , contextHelper {}", //
resourcesS.getReference().getProperty(Constants.SERVICE_ID), pattern, prefix, contextHelperSelector);
}

private void registerServlet(String servletName, String servletPattern, HttpServlet servlet,
String contextHelperName) {

Map<String, String> props = new HashMap<>();

String contextHelperSelector = "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "="
+ contextHelperName + ")";

props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, servletName);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, servletPattern);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
"(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + contextHelperName + ")");
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextHelperSelector);
props.put(Constants.SERVICE_SCOPE, Constants.SCOPE_PROTOTYPE);

ServiceRegistration<Servlet> servletService = this.bundleContext.registerService(Servlet.class, servlet,
new Hashtable<>(props));

this.servlets.add(servletService);

logger.debug("registered servlet with id: {} , name: {} , pattern {} , contextHelper {}", //
servletService.getReference().getProperty(Constants.SERVICE_ID), servletName, servletPattern,
contextHelperSelector);
}

public interface ResourcesService {
Expand Down Expand Up @@ -609,4 +663,5 @@ public UserManager getUserManager() {
public ComponentConfiguration getConfiguration() throws KuraException {
return consoleOptions.getConfiguration();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
import java.util.Map;
import java.util.Optional;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.eclipse.kura.audit.AuditContext;
import org.eclipse.kura.audit.AuditContext.Scope;
import org.eclipse.kura.web.Console;
Expand All @@ -37,9 +33,13 @@
import com.google.gwt.user.server.rpc.SerializationPolicy;
import com.google.gwt.user.server.rpc.SerializationPolicyLoader;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class OsgiRemoteServiceServlet extends KuraRemoteServiceServlet {

private final Logger auditLogger = LoggerFactory.getLogger("AuditLogger");
private static final Logger auditLogger = LoggerFactory.getLogger("AuditLogger");

private final Optional<RequiredPermissions> servicePermissionRequirements;
private final Map<Method, RequiredPermissions> methodPermissionRequirements = new HashMap<>();
Expand Down Expand Up @@ -100,13 +100,13 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws
* alternative approach.
*
* @param request
* the HTTP request being serviced
* the HTTP request being serviced
* @param moduleBaseURL
* as specified in the incoming payload
* as specified in the incoming payload
* @param strongName
* a strong name that uniquely identifies a serialization
* policy
* file
* a strong name that uniquely identifies a serialization
* policy
* file
* @return a {@link SerializationPolicy} for the given module base URL and
* strong name, or <code>null</code> if there is none
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2024 Eurotech and/or its affiliates and others
* Copyright (c) 2019, 2025 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -13,6 +13,7 @@
package org.eclipse.kura.web.session;

import java.io.IOException;
import java.util.Objects;

import org.osgi.framework.FrameworkUtil;
import org.osgi.service.servlet.context.ServletContextHelper;
Expand All @@ -27,16 +28,14 @@ public class HttpServletContextHelper extends ServletContextHelper {

public HttpServletContextHelper(SecurityHandler securityHandler) {
super(FrameworkUtil.getBundle(HttpServletContextHelper.class));

Objects.requireNonNull(securityHandler);
this.securityHandler = securityHandler;
}

@Override
public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {

if (this.securityHandler == null) {
return super.handleSecurity(request, response);
}

if (handleSecurityInternal(request, response)) {
return true;
}
Expand Down
Loading

0 comments on commit cc2f172

Please sign in to comment.